From b422e0ec8f65b5b7e59f3e8fd61ab3c9f59ad70c Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 5 May 2015 12:26:51 +1000 Subject: [PATCH 001/340] Update build.sbt --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0defedc..4b3a450 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ organization := "org.scala-lang.modules" name := "scala-java8-compat" -version := "0.3.0-SNAPSHOT" +version := "0.5.0-SNAPSHOT" // important!! must come here (why?) scalaModuleOsgiSettings From 82eba69c0a517977ccb292ad2bd62f7cc977ce1e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 6 May 2015 09:12:17 +1000 Subject: [PATCH 002/340] shields.io Maven badges; show 2.10 and 2.11 builds --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 85d1e6f..370a3aa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [![Maven Central 2.11](https://maven-badges.herokuapp.com/maven-central/org.scala-lang.modules/scala-java8-compat_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.scala-lang.modules/scala-java8-compat_2.11) +## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.10) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) A Java 8 compatibility kit for Scala. From a91294476a71cd0ef9b6a3ecb94a87a19b539416 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 12 May 2015 15:26:59 +1000 Subject: [PATCH 003/340] Add a generic deserializer for Java/Scala 2.12 lambdas Java support serialization of lambdas by using the serialization proxy pattern. Deserialization of a lambda uses `LambdaMetafactory` to create a new anonymous subclass. More details of the scheme are documented: https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/SerializedLambda.html From those docs: > SerializedLambda has a readResolve method that looks for a > (possibly private) static method called $deserializeLambda$ > in the capturing class, invokes that with itself as the first > argument, and returns the result. Lambda classes implementing > $deserializeLambda$ are responsible for validating that the > properties of the SerializedLambda are consistent with a lambda > actually captured by that class. The Java compiler generates code in `$deserializeLambda$` that switches on the implementation method name and signature to locate an invokedynamic instruction generated for the particular lambda expression. Then, the `SerializedLambda` is further unpacked, validating that this implementation method still represents the same functional interface as it did when it was serialized. (The source may have been recompiled in the interim.) In Java, serializable lambda expressions are the exception rather than the rule. In Scala, however, the serializability of `FunctionN` means that we would end up generating a large amount of code to support deserialization. Instead, we are pursuing an alternative approach in which the `$deserializeLambda$` method is a simple forwarder to the generic deserializer added here. This is capable of deserializing lambdas created by the Java compiler, although this is not its intended use case. The enclosed tests use Java lambdas. This generic deserializer also works by calling `LambdaMetafactory`, but it does so explicitly, rather than implicitly during linkage of the `invokedynamic` instruction. We have to mimic the caching property of `invokedynamic` instruction to ensure we reuse the classes when constructing. I originally tried using a central cache, but wasn't able to come up with a scheme to avoid potential classloader memory leaks. Instead, I now allow the caller to provide a cache. The scala compiler will host an instance of this cache in each class that hosts a lambda. This is analagous the the `MethodCache` used by reflective calls. If the name or signature of the implementation method has changed, we fail during deserialization with an `IllegalArgumentError.` However, we do not fail fast in a few cases that Java would, as we cannot reflect on the "current" functional interface supported by this implementation method. We just instantiate using the "previous" functional interface class/method. This might: 1. fail inside `LambdaMetafactory` if the new implementation method is not compatible with the old functional interface. 2. pass through `LambdaMetafactory` by chance, but fail when instantiating the class in other cases. For example: ``` % tail sandbox/test{1,2}.scala ==> sandbox/test1.scala <== class C { def test: (String => String) = { val s: String = "" (t) => s + t } } ==> sandbox/test2.scala <== class C { def test: (String, String) => String = { (s, t) => s + t } } % (for i in 1 2; do scalac -Ydelambdafy:method -Xprint:delambdafy sandbox/test$i.scala 2>&1 ; done) | grep 'def $anon' final private[this] def $anonfun$1(t: String, s$1: String): String = s$1.+(t); final private[this] def $anonfun$1(s: String, t: String): String = s.+(t); ``` 3. Silently create an instance of the old functional interface. For example, imagine switching from `FuncInterface1` to `FuncInterface2` where these were identical other than the name. I don't believe that these are showstoppers. Failing test case demonstrating overly weak cache --- .../java8/runtime/LambdaDeserializer.scala | 132 +++++++++++++ .../java8/runtime/LambdaDeserializerTest.java | 181 ++++++++++++++++++ 2 files changed, 313 insertions(+) create mode 100644 src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala create mode 100644 src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java diff --git a/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala b/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala new file mode 100644 index 0000000..f9609d1 --- /dev/null +++ b/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala @@ -0,0 +1,132 @@ +package scala.compat.java8.runtime + +import java.lang.invoke._ + +/** + * This class is only intended to be called by synthetic `$deserializeLambda$` method that the Scala 2.12 + * compiler will add to classes hosting lambdas. + * + * It is not intended to be consumed directly. + */ +object LambdaDeserializer { + /** + * Deserialize a lambda by calling `LambdaMetafactory.altMetafactory` to spin up a lambda class + * and instantiating this class with the captured arguments. + * + * A cache may be provided to ensure that subsequent deserialization of the same lambda expression + * is cheap, it amounts to a reflective call to the constructor of the previously created class. + * However, deserialization of the same lambda expression is not guaranteed to use the same class, + * concurrent deserialization of the same lambda expression may spin up more than one class. + * + * Assumptions: + * - No additional marker interfaces are required beyond `{java.io,scala.}Serializable`. These are + * not stored in `SerializedLambda`, so we can't reconstitute them. + * - No additional bridge methods are passed to `altMetafactory`. Again, these are not stored. + * + * @param lookup The factory for method handles. Must have access to the implementation method, the + * functional interface class, and `java.io.Serializable` or `scala.Serializable` as + * required. + * @param cache A cache used to avoid spinning up a class for each deserialization of a given lambda. May be `null` + * @param serialized The lambda to deserialize. Note that this is typically created by the `readResolve` + * member of the anonymous class created by `LambdaMetaFactory`. + * @return An instance of the functional interface + */ + def deserializeLambda(lookup: MethodHandles.Lookup, cache: java.util.Map[String, MethodHandle], serialized: SerializedLambda): AnyRef = { + def slashDot(name: String) = name.replaceAll("/", ".") + val loader = lookup.lookupClass().getClassLoader + val implClass = loader.loadClass(slashDot(serialized.getImplClass)) + + def makeCallSite: CallSite = { + import serialized._ + def parseDescriptor(s: String) = + MethodType.fromMethodDescriptorString(s, loader) + + val funcInterfaceSignature = parseDescriptor(getFunctionalInterfaceMethodSignature) + val instantiated = parseDescriptor(getInstantiatedMethodType) + val functionalInterfaceClass = loader.loadClass(slashDot(getFunctionalInterfaceClass)) + + val implMethodSig = parseDescriptor(getImplMethodSignature) + // Construct the invoked type from the impl method type. This is the type of a factory + // that will be generated by the meta-factory. It is a method type, with param types + // coming form the types of the captures, and return type being the functional interface. + val invokedType: MethodType = { + // 1. Add receiver for non-static impl methods + val withReceiver = getImplMethodKind match { + case MethodHandleInfo.REF_invokeStatic | MethodHandleInfo.REF_newInvokeSpecial => + implMethodSig + case _ => + implMethodSig.insertParameterTypes(0, implClass) + } + // 2. Remove lambda parameters, leaving only captures. Note: the receiver may be a lambda parameter, + // such as in `Function s = Object::toString` + val lambdaArity = funcInterfaceSignature.parameterCount() + val from = withReceiver.parameterCount() - lambdaArity + val to = withReceiver.parameterCount() + + // 3. Drop the lambda return type and replace with the functional interface. + withReceiver.dropParameterTypes(from, to).changeReturnType(functionalInterfaceClass) + } + + // Lookup the implementation method + val implMethod: MethodHandle = try { + findMember(lookup, getImplMethodKind, implClass, getImplMethodName, implMethodSig) + } catch { + case e: ReflectiveOperationException => throw new IllegalArgumentException("Illegal lambda deserialization", e) + } + + val flags: Int = LambdaMetafactory.FLAG_SERIALIZABLE | LambdaMetafactory.FLAG_MARKERS + val isScalaFunction = functionalInterfaceClass.getName.startsWith("scala.Function") + val markerInterface: Class[_] = loader.loadClass(if (isScalaFunction) ScalaSerializable else JavaIOSerializable) + + LambdaMetafactory.altMetafactory( + lookup, getFunctionalInterfaceMethodName, invokedType, + + /* samMethodType = */ funcInterfaceSignature, + /* implMethod = */ implMethod, + /* instantiatedMethodType = */ instantiated, + /* flags = */ flags.asInstanceOf[AnyRef], + /* markerInterfaceCount = */ 1.asInstanceOf[AnyRef], + /* markerInterfaces[0] = */ markerInterface, + /* bridgeCount = */ 0.asInstanceOf[AnyRef] + ) + } + + val key = serialized.getImplMethodName + " : " + serialized.getImplMethodSignature + val factory: MethodHandle = if (cache == null) { + makeCallSite.getTarget + } else cache.get(key) match { + case null => + val callSite = makeCallSite + val temp = callSite.getTarget + cache.put(key, temp) + temp + case target => target + } + + val captures = Array.tabulate(serialized.getCapturedArgCount)(n => serialized.getCapturedArg(n)) + factory.invokeWithArguments(captures: _*) + } + + private val ScalaSerializable = "scala.Serializable" + + private val JavaIOSerializable = { + // We could actually omit this marker interface as LambdaMetaFactory will add it if + // the FLAG_SERIALIZABLE is set and of the provided markers extend it. But the code + // is cleaner if we uniformly add a single marker, so I'm leaving it in place. + "java.io.Serializable" + } + + private def findMember(lookup: MethodHandles.Lookup, kind: Int, owner: Class[_], + name: String, signature: MethodType): MethodHandle = { + kind match { + case MethodHandleInfo.REF_invokeStatic => + lookup.findStatic(owner, name, signature) + case MethodHandleInfo.REF_newInvokeSpecial => + lookup.findConstructor(owner, signature) + case MethodHandleInfo.REF_invokeVirtual | MethodHandleInfo.REF_invokeInterface => + lookup.findVirtual(owner, name, signature) + case MethodHandleInfo.REF_invokeSpecial => + lookup.findSpecial(owner, name, signature, owner) + } + } +} diff --git a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java new file mode 100644 index 0000000..3a03750 --- /dev/null +++ b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java @@ -0,0 +1,181 @@ +package scala.compat.java8.runtime; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; + +public final class LambdaDeserializerTest { + private LambdaHost lambdaHost = new LambdaHost(); + + @Test + public void serializationPrivate() { + F1 f1 = lambdaHost.lambdaBackedByPrivateImplMethod(); + Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); + } + + @Test + public void serializationStatic() { + F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); + Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); + } + + @Test + public void serializationVirtualMethodReference() { + F1 f1 = lambdaHost.lambdaBackedByVirtualMethodReference(); + Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); + } + + @Test + public void serializationInterfaceMethodReference() { + F1 f1 = lambdaHost.lambdaBackedByInterfaceMethodReference(); + I i = new I() { + }; + Assert.assertEquals(f1.apply(i), reconstitute(f1).apply(i)); + } + + @Test + public void serializationStaticMethodReference() { + F1 f1 = lambdaHost.lambdaBackedByStaticMethodReference(); + Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); + } + + @Test + public void serializationNewInvokeSpecial() { + F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); + Assert.assertEquals(f1.apply(), reconstitute(f1).apply()); + } + + @Test + public void uncached() { + F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); + F0 reconstituted1 = reconstitute(f1); + F0 reconstituted2 = reconstitute(f1); + Assert.assertNotEquals(reconstituted1.getClass(), reconstituted2.getClass()); + } + + @Test + public void cached() { + HashMap cache = new HashMap<>(); + F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); + F0 reconstituted1 = reconstitute(f1, cache); + F0 reconstituted2 = reconstitute(f1, cache); + Assert.assertEquals(reconstituted1.getClass(), reconstituted2.getClass()); + } + + @Test + public void implMethodNameChanged() { + F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); + SerializedLambda sl = writeReplace(f1); + checkIllegalAccess(copySerializedLambda(sl, sl.getImplMethodName() + "___", sl.getImplMethodSignature())); + } + + @Test + public void implMethodSignatureChanged() { + F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); + SerializedLambda sl = writeReplace(f1); + checkIllegalAccess(copySerializedLambda(sl, sl.getImplMethodName(), sl.getImplMethodSignature().replace("Boolean", "Integer"))); + } + + private void checkIllegalAccess(SerializedLambda serialized) { + try { + LambdaDeserializer.deserializeLambda(MethodHandles.lookup(), null, serialized); + throw new AssertionError(); + } catch (IllegalArgumentException iae) { + if (!iae.getMessage().contains("Illegal lambda deserialization")) { + Assert.fail("Unexpected message: " + iae.getMessage()); + } + } + } + + private SerializedLambda copySerializedLambda(SerializedLambda sl, String implMethodName, String implMethodSignature) { + Object[] captures = new Object[sl.getCapturedArgCount()]; + for (int i = 0; i < captures.length; i++) { + captures[i] = sl.getCapturedArg(i); + } + return new SerializedLambda(loadClass(sl.getCapturingClass()), sl.getFunctionalInterfaceClass(), sl.getFunctionalInterfaceMethodName(), + sl.getFunctionalInterfaceMethodSignature(), sl.getImplMethodKind(), sl.getImplClass(), implMethodName, implMethodSignature, + sl.getInstantiatedMethodType(), captures); + } + + private Class loadClass(String className) { + try { + return Class.forName(className.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + private A reconstitute(A f1) { + return reconstitute(f1, null); + } + + @SuppressWarnings("unchecked") + private A reconstitute(A f1, java.util.HashMap cache) { + try { + return (A) LambdaDeserializer.deserializeLambda(LambdaHost.lookup(), cache, writeReplace(f1)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private SerializedLambda writeReplace(A f1) { + try { + Method writeReplace = f1.getClass().getDeclaredMethod("writeReplace"); + writeReplace.setAccessible(true); + return (SerializedLambda) writeReplace.invoke(f1); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} + + +interface F1 extends Serializable { + B apply(A a); +} + +interface F0 extends Serializable { + A apply(); +} + +class LambdaHost { + public F1 lambdaBackedByPrivateImplMethod() { + int local = 42; + return (b) -> Arrays.asList(local, b ? "true" : "false", LambdaHost.this).toString(); + } + + @SuppressWarnings("Convert2MethodRef") + public F1 lambdaBackedByStaticImplMethod() { + return (b) -> String.valueOf(b); + } + + public F1 lambdaBackedByStaticMethodReference() { + return String::valueOf; + } + + public F1 lambdaBackedByVirtualMethodReference() { + return Object::toString; + } + + public F1 lambdaBackedByInterfaceMethodReference() { + return I::i; + } + + public F0 lambdaBackedByConstructorCall() { + return String::new; + } + + public static MethodHandles.Lookup lookup() { + return MethodHandles.lookup(); + } +} + +interface I { + default String i() { return "i"; }; +} From 921b212b609bc8aa08ccac46e3c76048e2e6978e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 17 May 2015 18:41:29 +1000 Subject: [PATCH 004/340] Test static lambda hoisting works via LambdaDeserializer LambdaMetafactory returns a ConstantCallSite bound to a shared instance of a lambda, rather than a reference to the no-arg constructor. This is a technique to avoid unnecessary allocations. This test checks that we preserve this property when deserializing. --- .../compat/java8/runtime/LambdaDeserializerTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java index 3a03750..723e56c 100644 --- a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java +++ b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java @@ -69,6 +69,18 @@ public void cached() { Assert.assertEquals(reconstituted1.getClass(), reconstituted2.getClass()); } + @Test + public void cachedStatic() { + HashMap cache = new HashMap<>(); + F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); + // Check that deserialization of a static lambda always returns the + // same instance. + Assert.assertSame(reconstitute(f1, cache), reconstitute(f1, cache)); + + // (as is the case with regular invocation.) + Assert.assertSame(f1, lambdaHost.lambdaBackedByStaticImplMethod()); + } + @Test public void implMethodNameChanged() { F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); From 0458563e21da35b922fe2864671650560cc3048d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 22 May 2015 11:57:30 +1000 Subject: [PATCH 005/340] Bump version to v0.6.0 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4b3a450..417e8ba 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ organization := "org.scala-lang.modules" name := "scala-java8-compat" -version := "0.5.0-SNAPSHOT" +version := "0.6.0-SNAPSHOT" // important!! must come here (why?) scalaModuleOsgiSettings From 2fc8bbdaeb1648fb761eaa793849a0e03b84569e Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 13 May 2015 10:33:35 +0200 Subject: [PATCH 006/340] Update scala modules sbt plugin to 1.0.3 Also update to Scala 2.11.6. --- build.sbt | 16 ++-------------- project/plugins.sbt | 4 +--- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/build.sbt b/build.sbt index 417e8ba..b8cec2f 100644 --- a/build.sbt +++ b/build.sbt @@ -1,10 +1,6 @@ -import com.typesafe.tools.mima.plugin.{MimaPlugin, MimaKeys} - scalaModuleSettings -scalaVersion := "2.11.5" - -snapshotScalaBinaryVersion := "2.11.5" +scalaVersion := "2.11.6" organization := "org.scala-lang.modules" @@ -23,15 +19,7 @@ libraryDependencies += "junit" % "junit" % "4.11" % "test" libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test" -MimaPlugin.mimaDefaultSettings - -MimaKeys.previousArtifact := None - -// run mima during tests -test in Test := { - MimaKeys.reportBinaryIssues.value - (test in Test).value -} +mimaPreviousVersion := None testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a") diff --git a/project/plugins.sbt b/project/plugins.sbt index 5f604e6..25f3373 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.2") - -addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.6") +addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.3") From 3aa343e9b894495626ce8a4767b6c550de1db5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Mickevi=C4=8Dius?= Date: Thu, 4 Jun 2015 11:54:35 +0300 Subject: [PATCH 007/340] Fix link to concurrent converters API --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 370a3aa..ecf5887 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ class Test { ## Converters between `scala.concurrent` and `java.util.concurrent` - - [API](src/main/java/scala/compat/java8/FutureConverters.java) + - [API](src/main/scala/scala/compat/java8/FutureConverters.scala) - [Test Cases](src/test/java/scala/compat/java8/FutureConvertersTest.java) ## Converters between `scala.Option` and `java.util` classes `Optional`, `OptionalDouble`, `OptionalInt`, and `OptionalLong`. From 4bb7192f394297c09edba08da56fdc181fd33c10 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 5 Jun 2015 06:24:02 +0200 Subject: [PATCH 008/340] Make function bridge interfaces serializable --- build.sbt | 2 ++ project/CodeGen.scala | 6 +++--- .../java/scala/compat/java8/LambdaTest.java | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index b8cec2f..5bd3d69 100644 --- a/build.sbt +++ b/build.sbt @@ -17,6 +17,8 @@ OsgiKeys.privatePackage := List("scala.concurrent.java8.*") libraryDependencies += "junit" % "junit" % "4.11" % "test" +libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test" + libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test" mimaPreviousVersion := None diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 0e0234c..c916af3 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -40,7 +40,7 @@ object CodeGen { |$packaging | |@FunctionalInterface - |public interface JFunction0 extends scala.Function0 { + |public interface JFunction0 extends scala.Function0, java.io.Serializable { | default void $initName() { | }; |""".stripMargin @@ -51,7 +51,7 @@ object CodeGen { |$packaging | |@FunctionalInterface - |public interface JFunction1 extends scala.Function1 { + |public interface JFunction1 extends scala.Function1, java.io.Serializable { | default void $initName() { | }; | @@ -77,7 +77,7 @@ object CodeGen { |$packaging | |@FunctionalInterface - |public interface JFunction$n<$tparams, R> extends scala.Function$n<$tparams, R> { + |public interface JFunction$n<$tparams, R> extends scala.Function$n<$tparams, R>, java.io.Serializable { | default void $initName() { | }; | diff --git a/src/test/java/scala/compat/java8/LambdaTest.java b/src/test/java/scala/compat/java8/LambdaTest.java index c626083..84a586d 100644 --- a/src/test/java/scala/compat/java8/LambdaTest.java +++ b/src/test/java/scala/compat/java8/LambdaTest.java @@ -3,12 +3,16 @@ */ package scala.compat.java8; +import org.apache.commons.lang3.SerializationUtils; import scala.runtime.*; + +import static junit.framework.Assert.assertEquals; import static scala.compat.java8.JFunction.*; import static scala.compat.java8.TestAPI.*; import org.junit.Test; + public class LambdaTest { @Test public void lambdaDemo() { @@ -95,6 +99,21 @@ public void lambdaDemo() { acceptFunction22Unit( proc((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return;})); } + @Test + public void isSerializable() { + scala.compat.java8.JFunction0 f0 = () -> "foo"; + assertEquals("foo", SerializationUtils.clone(f0).apply()); + + scala.compat.java8.JFunction1 f1 = (a) -> a.toUpperCase(); + assertEquals("FOO", SerializationUtils.clone(f1).apply("foo")); + + scala.compat.java8.JFunction2 f2 = (a, b) -> a + b; + assertEquals("foobar", SerializationUtils.clone(f2).apply("foo", "bar")); + + scala.compat.java8.JFunction3 f3 = (a, b, c) -> a + b + c; + assertEquals("foobarbaz", SerializationUtils.clone(f3).apply("foo", "bar", "baz")); + } + private static scala.concurrent.Future futureExample( scala.concurrent.Future future, scala.concurrent.ExecutionContext ec) { return future.map(func(s -> s.toUpperCase()), ec).map(func(s -> s.length()), ec); From b2178bb3e322f782c92b74698aff6d273f6153e9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 5 Jun 2015 06:30:35 +0200 Subject: [PATCH 009/340] Drop support for Scala 2.10 Focussing on 2.11 and 2.12 instead. --- .travis.yml | 3 +-- README.md | 2 +- project/CodeGen.scala | 35 ++--------------------------------- 3 files changed, 4 insertions(+), 36 deletions(-) diff --git a/.travis.yml b/.travis.yml index a5a7a74..aa3fefb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,7 @@ env: script: - admin/build.sh scala: - - 2.10.4 - - 2.11.5 + - 2.11.6 jdk: - oraclejdk8 notifications: diff --git a/README.md b/README.md index ecf5887..2493c0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.10) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) +## scala-java8-compat [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) A Java 8 compatibility kit for Scala. diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 0e0234c..1428e34 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -331,26 +331,9 @@ object CodeGen { |} |""".stripMargin.trim } - // andThen / compose variants are no longer needed under 2.11 (@unspecialized has been fixed), - // but harmless. With them, we can use the same artifact for 2.10 and 2.11 - val compose = specialized("compose", function1Spec) { - case (name, List(t1, r1)) => - s""" - |default scala.Function1 $name(scala.Function1 g) { - | return compose(g); - |}""".stripMargin.trim - } - val andThen = specialized("andThen", function1Spec) { - case (name, List(t1, r1)) => - s""" - |default scala.Function1 $name(scala.Function1 g) { - | return andThen(g); - |}""".stripMargin.trim - } - indent(List(apply, compose, andThen).mkString("\n\n")) + indent(List(apply).mkString("\n\n")) } - // No longer needed under 2.11 (@unspecialized has been fixed), but harmless to keep around to avoid cross-publishing this artifact. private def function2SpecMethods = { val apply = specialized("apply", function2Spec) { case (name, List(t1, t2, r)) => @@ -363,21 +346,7 @@ object CodeGen { |} |""".stripMargin.trim } - val curried = specialized("curried", function2Spec) { - case (name, List(t1, t2, r)) => - s""" - |default scala.Function1 $name() { - | return curried(); - |}""".stripMargin.trim - } - val tupled = specialized("tupled", function2Spec) { - case (name, List(t1, t2, r)) => - s""" - |default scala.Function1 $name() { - | return tupled(); - |}""".stripMargin.trim - } - indent(List(apply, curried, tupled).mkString("\n\n")) + indent(List(apply).mkString("\n\n")) } def specializedSuffix(tparamNames: List[String], tps: List[Type]): String = { From 7b6c7562770d8be43095f7085d8125b13d3c4dd7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 28 Jul 2015 16:41:07 +1000 Subject: [PATCH 010/340] Opt in to new Travis CI container based builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a5a7a74..1ee9829 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: scala +sudo: false env: global: - PUBLISH_JDK=oraclejdk8 From de7d42cfa4062d7c6de5de5d7395df2a894393e8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 31 May 2015 14:41:37 -0700 Subject: [PATCH 011/340] Added function converter capability based on initial reflection work from Jason Zaugg. If you have something from java.util.functions, you should be able to ``` import scala.compat.java8.FunctionConverters._ ``` and then use `.asScala` to convert to the corresponding Scala function. If you have a Scala function, use `.asJava` to convert to the best-matching item from java.util.functions. If you want a function that isn't the best match, use the corresponding `asJavaInterfaceName` method, e.g. ``` asJavaUnaryOperator((i: Int) => i+1) // Best match would be IntUnaryOperator The code is created with a code generator that needs to run in Scala 2.11+, but SBT runs 2.10 by default. Thus, build.sbtt was reworked to be multi-module (the sub-module is the code generator). --- build.sbt | 191 ++++++----- fnGen/WrapFnGen.scala | 300 ++++++++++++++++++ .../scala/compat/java8/WrapperTraits.scala | 13 + 3 files changed, 420 insertions(+), 84 deletions(-) create mode 100644 fnGen/WrapFnGen.scala create mode 100644 src/main/scala/scala/compat/java8/WrapperTraits.scala diff --git a/build.sbt b/build.sbt index 5bd3d69..fa1d549 100644 --- a/build.sbt +++ b/build.sbt @@ -1,91 +1,114 @@ -scalaModuleSettings - -scalaVersion := "2.11.6" - -organization := "org.scala-lang.modules" - -name := "scala-java8-compat" - -version := "0.6.0-SNAPSHOT" - -// important!! must come here (why?) -scalaModuleOsgiSettings - -OsgiKeys.exportPackage := Seq(s"scala.compat.java8.*;version=${version.value}") - -OsgiKeys.privatePackage := List("scala.concurrent.java8.*") - -libraryDependencies += "junit" % "junit" % "4.11" % "test" - -libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test" - -libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test" - -mimaPreviousVersion := None - -testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a") - -sourceGenerators in Compile <+= sourceManaged in Compile map { dir => - def write(name: String, content: String) = { - val f = dir / "scala" / "compat" / "java8" / s"${name}.java" - IO.write(f, content) - f - } - ( - Seq(write("JFunction", CodeGen.factory)) ++ - (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ - (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ - CodeGen.specializedF0.map((write _).tupled) ++ - CodeGen.specializedF1.map((write _).tupled) ++ - CodeGen.specializedF2.map((write _).tupled) - ) -} - -sourceGenerators in Test <+= sourceManaged in Test map { dir => - def write(name: String, content: String) = { - val f = dir / "scala" / "compat" / "java8" / s"${name}.java" - IO.write(f, content) - f - } - Seq(write("TestApi", CodeGen.testApi)) -} - -initialize := { - // Run previously configured inialization... - initialize.value - // ... and then check the Java version. - val specVersion = sys.props("java.specification.version") - if (Set("1.5", "1.6", "1.7") contains specVersion) - sys.error("Java 8 or higher is required for this project.") -} - val disableDocs = sys.props("nodocs") == "true" -publishArtifact in packageDoc := !disableDocs - lazy val JavaDoc = config("genjavadoc") extend Compile -sources in (Compile, doc) := { - val orig = (sources in (Compile, doc)).value - orig.filterNot(_.getName.endsWith(".java")) // raw types not cooked by scaladoc: https://issues.scala-lang.org/browse/SI-8449 +def jwrite(dir: java.io.File)(name: String, content: String) = { + val f = dir / "scala" / "compat" / "java8" / s"${name}.java" + IO.write(f, content) + f } -inConfig(JavaDoc)(Defaults.configSettings) ++ (if (disableDocs) Nil else Seq( - packageDoc in Compile <<= packageDoc in JavaDoc, - sources in JavaDoc <<= (target, compile in Compile, sources in Compile) map {(t, c, s) => - val allJavaSources = (t / "java" ** "*.java").get ++ s.filter(_.getName.endsWith(".java")) - allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc - }, - javacOptions in JavaDoc := Seq(), - artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.8" cross CrossVersion.full), - scalacOptions in Compile <+= target map (t => "-P:genjavadoc:out=" + (t / "java")) -)) - -initialCommands := -"""|import scala.concurrent._ - |import ExecutionContext.Implicits.global - |import java.util.concurrent.{CompletionStage,CompletableFuture} - |import scala.compat.java8.FutureConverter._ - |""".stripMargin +lazy val commonSettings = Seq( + scalaVersion := "2.11.6", + organization := "org.scala-lang.modules", + version := "0.6.0-SNAPSHOT", + libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, + libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value +) + +lazy val fnGen = (project in file("fnGen")). + settings(commonSettings: _*). + settings( + fork in run := true // Needed if you run this project directly + ) +lazy val root = (project in file(".")). + dependsOn(fnGen). + settings(scalaModuleSettings: _*). + settings(commonSettings: _*). + settings( + name := "scala-java8-compat" + ). + settings( + // important!! must come here (why?) + scalaModuleOsgiSettings: _* + ). + settings( + fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath + + OsgiKeys.exportPackage := Seq(s"scala.compat.java8.*;version=${version.value}"), + + OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), + + libraryDependencies += "junit" % "junit" % "4.11" % "test", + + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test", + + libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test", + + mimaPreviousVersion := None, + + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), + + (sourceGenerators in Compile) += Def.task { + val out = (sourceManaged in Compile).value + if (!out.exists) IO.createDirectory(out) + val canon = out.getCanonicalPath + val args = (new File(canon, "FunctionConverters.scala")).toString :: Nil + val runTarget = (mainClass in Compile in fnGen).value getOrElse "No main class defined for function conversion generator" + val classPath = (fullClasspath in Compile in fnGen).value + toError(runner.value.run(runTarget, classPath.files, args, streams.value.log)) + (out ** "*.scala").get + }.taskValue, + + sourceGenerators in Compile <+= sourceManaged in Compile map { dir => + val write = jwrite(dir) _ + Seq(write("JFunction", CodeGen.factory)) ++ + (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ + (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ + CodeGen.specializedF0.map(write.tupled) ++ + CodeGen.specializedF1.map(write.tupled) ++ + CodeGen.specializedF2.map(write.tupled) + }, + + sourceGenerators in Test <+= sourceManaged in Test map { dir => + Seq(jwrite(dir)("TestApi", CodeGen.testApi)) + }, + + initialize := { + // Run previously configured inialization... + initialize.value + // ... and then check the Java version. + val specVersion = sys.props("java.specification.version") + if (Set("1.5", "1.6", "1.7") contains specVersion) + sys.error("Java 8 or higher is required for this project.") + }, + + publishArtifact in packageDoc := !disableDocs, + + sources in (Compile, doc) := { + val orig = (sources in (Compile, doc)).value + orig.filterNot(_.getName.endsWith(".java")) // raw types not cooked by scaladoc: https://issues.scala-lang.org/browse/SI-8449 + } + ). + settings( + (inConfig(JavaDoc)(Defaults.configSettings) ++ (if (disableDocs) Nil else Seq( + packageDoc in Compile <<= packageDoc in JavaDoc, + sources in JavaDoc <<= (target, compile in Compile, sources in Compile) map {(t, c, s) => + val allJavaSources = (t / "java" ** "*.java").get ++ s.filter(_.getName.endsWith(".java")) + allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc + }, + javacOptions in JavaDoc := Seq(), + artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.8" cross CrossVersion.full), + scalacOptions in Compile <+= target map (t => "-P:genjavadoc:out=" + (t / "java")) + ))): _* + ). + settings( + initialCommands := + """|import scala.concurrent._ + |import ExecutionContext.Implicits.global + |import java.util.concurrent.{CompletionStage,CompletableFuture} + |import scala.compat.java8.FutureConverter._ + |""".stripMargin + ) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala new file mode 100644 index 0000000..7ee0b4c --- /dev/null +++ b/fnGen/WrapFnGen.scala @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2015 Typesafe Inc. + */ + +object WrapFnGen { + val copyright = + s""" + |/* + | * Copyright (C) 2015, Typesafe Inc. + | * This file auto-generated by WrapFnGen.scala. Do not modify directly. + | */ + |""".stripMargin + + val packaging = "package scala.compat.java8" + + import scala.tools.nsc._ + import scala.reflect.internal._ + val settings = new Settings(msg => sys.error(msg)) + settings.usejavacp.value = true + val compiler = new Global(settings) + val run = new compiler.Run + + import compiler._, definitions._ + + + implicit class IndentMe(v: Vector[String]) { + def indent: Vector[String] = v.map(" " + _) + } + + implicit class FlattenMe(v: Vector[Vector[String]]) { + def mkVec(join: String = ""): Vector[String] = { + val vb = Vector.newBuilder[String] + var first = true + v.foreach{ vi => + if (!first) vb += join + first = false + vb ++= vi + } + vb.result() + } + } + + implicit class DoubleFlattenMe(v: Vector[Vector[Vector[String]]]) { + def mkVecVec(join: String = ""): Vector[String] = { + val vb = Vector.newBuilder[String] + var first = true + v.foreach{ vi => + if (!first) { vb += join; vb += join } + first = false + var ifirst = true + vi.foreach{ vj => + if (!ifirst) vb += join + ifirst = false + vb ++= vj + } + } + vb.result() + } + } + + implicit class SplitMyLinesAndStuff(s: String) { + def toVec = s.linesIterator.toVector + def nonBlank = s.trim.length > 0 + } + + implicit class TreeToText(t: Tree) { + def text = showCode(t).replace("$", "").linesIterator.toVector + } + + case class Prioritized(lines: Vector[String], priority: Int) { + def withPriority(i: Int) = copy(priority = i) + } + + case class SamConversionCode( + base: String, + wrappedAsScala: Vector[String], + implicitToScala: Vector[String], + asScalaDef: Vector[String], + wrappedAsJava: Vector[String], + asJavaAnyVal: Vector[String], + implicitToJava: Prioritized, + asJavaDef: Vector[String] + ) { + def impls: Vector[Vector[String]] = Vector(wrappedAsScala, wrappedAsJava, asJavaAnyVal) + def defs: Vector[Vector[String]] = Vector(asScalaDef, asJavaDef) + def convs: Vector[Vector[String]] = Vector(implicitToScala, implicitToJava.lines) + def withPriority(i: Int): SamConversionCode = copy(implicitToJava = implicitToJava.withPriority(i)) + } + object SamConversionCode { + def apply(scc: SamConversionCode*): (Vector[String], Vector[Vector[String]]) = { + val sccDepthSet = scc.map(_.implicitToJava.priority).toSet + val codes = + { + if (sccDepthSet != (0 to sccDepthSet.max).toSet) { + val sccDepthMap = sccDepthSet.toList.sorted.zipWithIndex.toMap + scc.map(x => x.withPriority(sccDepthMap(x.implicitToJava.priority))) + } + else scc + }.toVector.sortBy(_.base) + def priorityName(n: Int, pure: Boolean = false): String = { + val pre = + if (n <= 0) + if (pure) "functionConverters" + else s"package object ${priorityName(n, pure = true)}" + else + if (pure) s"Priority${n}FunctionConverters" + else s"trait ${priorityName(n, pure = true)}" + if (!pure && n < sccDepthSet.size) s"$pre extends ${priorityName(n+1, pure = true)}" else pre + } + val impls = + "package functionConverterImpls {" +: { + codes.map(_.impls).mkVecVec().indent + } :+ "}" + val traits = codes.filter(_.implicitToJava.priority > 0).groupBy(_.implicitToJava.priority).toVector.sortBy(- _._1).map{ case (k,vs) => + s"trait Priority${k}FunctionConverters {" +: + s" import functionConverterImpls._" +: + s" " +: + vs.map(_.implicitToJava.lines).mkVec().indent :+ + s"}" + } + val explicitDefs = codes.map(_.defs).mkVecVec() + val packageObj = + s"${priorityName(0)} {" +: + s" import functionConverterImpls._" +: + s" " +: + { + explicitDefs.indent ++ + codes.filter(_.implicitToJava.priority == 0).map(_.convs).mkVecVec().indent + } :+ "}" + (impls, traits :+ packageObj) + } + } + + private def buildWrappersViaReflection: Seq[SamConversionCode] = { + + val pack: Symbol = rootMirror.getPackageIfDefined(TermName("java.util.function")) + + case class Jfn(iface: Symbol, sam: Symbol) { + lazy val genericCount = iface.typeParams.length + lazy val name = sam.name.toTermName + lazy val title = iface.name.encoded + lazy val params = sam.info.params + lazy val sig = sam typeSignatureIn iface.info + lazy val pTypes = sig.params.map(_.info) + lazy val rType = sig.resultType + def arity = params.length + } + + val sams = pack.info.decls. + map(d => (d, d.typeSignature.members.filter(_.isAbstract).toList)). + collect{ case (d, m :: Nil) if d.isAbstract => Jfn(d, m) } + + def generate(jfn: Jfn): SamConversionCode = { + def mkRef(tp: Type): Tree = if (tp.typeSymbol.isTypeParameter) Ident(tp.typeSymbol.name.toTypeName) else tq"$tp" + + // Types for the Java SAM and the corresponding Scala function, plus all type parameters + val scalaType = gen.mkAttributedRef(FunctionClass(jfn.arity)) + val javaType = gen.mkAttributedRef(jfn.iface) + val tnParams: List[TypeName] = jfn.iface.typeParams.map(_.name.toTypeName) + val tdParams: List[TypeDef] = tnParams.map(TypeDef(NoMods, _, Nil, EmptyTree)) + val javaTargs: List[Tree] = tdParams.map(_.name).map(Ident(_)) + val scalaTargs: List[Tree] = jfn.pTypes.map(mkRef) :+ mkRef(jfn.rType) + + // Conversion wrappers have three or four components that we need to name + // (1) The wrapper class that wraps a Java SAM as Scala function, or vice versa (ClassN) + // (2) A value class that provides .asJava or .asScala to request the conversion (ValCN) + // (3) A name for an explicit conversion method (DefN) + // (4) If nested-trait lookup is needed to pick types, an implicit conversion method name (ImpN) + + // Names for Java conversions to Scala + val j2sClassN = TypeName("FromJava" + jfn.title) + val j2sValCN = TypeName("Rich" + jfn.title + "As" + scalaType.name.encoded) + val j2sDefN = TermName("asScalaFrom" + jfn.title) + + // Names for Scala conversions to Java + val s2jClassN = TypeName("AsJava" + jfn.title) + val s2jValCN = TypeName("Rich" + scalaType.name.encoded + "As" + jfn.title) + val s2jDefN = TermName("asJava" + jfn.title) + val s2jImpN = TermName("enrichAsJava" + jfn.title) + + // Argument lists for the function / SAM + val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) => + ValDef(NoMods, p.name.toTermName, if (t.typeSymbol.isTypeParameter) Ident(t.typeSymbol.name) else gen.mkAttributedRef(t.typeSymbol), EmptyTree) + } + val vParamRefs = vParams.map(_.name).map(Ident(_)) + + val j2sClassTree = + q"""class $j2sClassN[..$tdParams](jf: $javaType[..$javaTargs]) extends $scalaType[..$scalaTargs] { + def apply(..$vParams) = jf.${jfn.name}(..$vParamRefs) + }""" + + val j2sValCTree = + q"""implicit class $j2sValCN[..$tdParams](private val underlying: $javaType[..$javaTargs]) extends AnyVal { + @inline def asScala: $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](underlying) + }""" + + val j2sDefTree = + q"""def $j2sDefN[..$tdParams](jf: $javaType[..$javaTargs]): $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](jf)""" + + val s2jClassTree = + q"""class $s2jClassN[..$tdParams](sf: $scalaType[..$scalaTargs]) extends $javaType[..$javaTargs] { + def ${jfn.name}(..$vParams) = sf.apply(..$vParamRefs) + }""" + + val s2jValCTree = + q"""class $s2jValCN[..$tdParams](private val underlying: $scalaType[..$scalaTargs]) extends AnyVal { + @inline def asJava: $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](underlying) + }""" + + val s2jDefTree = + q"""def $s2jDefN[..$tdParams](sf: $scalaType[..$scalaTargs]): $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](sf)""" + + // This is especially tricky because functions are contravariant in their arguments + // Need to prevent e.g. Any => String from "downcasting" itself to Int => String; we want the more exact conversion + val s2jImpTree: (Tree, Int) = + if (jfn.pTypes.forall(! _.isFinalType) && jfn.sig == jfn.sam.typeSignature) + ( + q"""implicit def $s2jImpN[..$tdParams](sf: $scalaType[..$scalaTargs]): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf)""", + tdParams.length + ) + else { + // Some types are not generic or are re-used; we had better catch those. + // Making up new type names, so switch everything to TypeName or TypeDef + // Instead of foo[A](f: (Int, A) => Long): Fuu[A] = new Foo[A](f) + // we want foo[X, A](f: (X, A) => Long)(implicit evX: Int =:= X): Fuu[A] = new Foo[A](f.asInstanceOf[(Int, A) => Long]) + // Instead of bar[A](f: A => A): Brr[A] = new Foo[A](f) + // we want bar[A, B](f: A => B)(implicit evB: A =:= B): Brr[A] = new Foo[A](f.asInstanceOf[A => B]) + val An = "A(\\d+)".r + val numberedA = collection.mutable.Set.empty[Int] + val evidences = collection.mutable.ArrayBuffer.empty[(TypeName, TypeName)] + numberedA ++= scalaTargs.map(_.toString).collect{ case An(digits) if (digits.length < 10) => digits.toInt } + val scalafnTnames = (jfn.pTypes :+ jfn.rType).zipWithIndex.map{ + case (pt, i) if (i < jfn.pTypes.length && pt.isFinalType) || (!pt.isFinalType && jfn.pTypes.take(i).exists(_ == pt)) => + val j = Iterator.from(i).dropWhile(numberedA).next + val genericName = TypeName(s"A$j") + numberedA += j + evidences += ((genericName, pt.typeSymbol.name.toTypeName)) + genericName + case (pt, _) => pt.typeSymbol.name.toTypeName + } + val scalafnTdefs = scalafnTnames. + map(TypeDef(NoMods, _, Nil, EmptyTree)). + dropRight(if (jfn.rType.isFinalType) 1 else 0) + val evs = evidences.map{ case (generic, specific) => ValDef(NoMods, TermName("ev"+generic.toString), tq"$generic =:= $specific", EmptyTree) } + val tree = + q"""implicit def $s2jImpN[..$scalafnTdefs](sf: $scalaType[..$scalafnTnames])(implicit ..$evs): $s2jValCN[..$tnParams] = + new $s2jValCN[..$tnParams](sf.asInstanceOf[$scalaType[..$scalaTargs]]) + """ + val depth = numberedA.size + (tree, tdParams.length) + } + + SamConversionCode( + base = jfn.title, + wrappedAsScala = j2sClassTree.text, + implicitToScala = j2sValCTree.text, + asScalaDef = j2sDefTree.text, + wrappedAsJava = s2jClassTree.text, + asJavaAnyVal = s2jValCTree.text, + implicitToJava = s2jImpTree match { case (t,d) => Prioritized(t.text, d) }, + asJavaDef = s2jDefTree.text + ) + } + + sams.toSeq.map(generate) + } + + lazy val converterContents = + s""" + |$copyright + | + |$packaging + | + |import language.implicitConversions + | + | + |""".stripMargin + + (SamConversionCode(buildWrappersViaReflection: _*) match { + case (impls, defs) => impls.mkString("\n") + "\n\n\n\n" + defs.map(_.mkString("\n")).mkString("\n\n\n\n") + }) + + def sameText(f: java.io.File, text: String): Boolean = { + val x = scala.io.Source.fromFile(f) + val lines = try { x.getLines.toVector } finally { x.close } + lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) + } + + def write(f: java.io.File, text: String) { + if (!f.exists || !sameText(f, text)) { + val p = new java.io.PrintWriter(f) + try { p.println(text) } + finally { p.close() } + } + } + + def main(args: Array[String]) { + val names = args.iterator.map(x => new java.io.File(x)) + write(names.next, converterContents) + } +} diff --git a/src/main/scala/scala/compat/java8/WrapperTraits.scala b/src/main/scala/scala/compat/java8/WrapperTraits.scala new file mode 100644 index 0000000..da0125c --- /dev/null +++ b/src/main/scala/scala/compat/java8/WrapperTraits.scala @@ -0,0 +1,13 @@ +package scala.compat.java8 + +/** A trait that indicates that the class is or can be converted to a Scala version by wrapping a Java class */ +trait WrappedAsScala[S] { + /** Returns an appropriate Scala version */ + def asScala: S +} + +/** A trait that indicates that the class is or can be converted to a Java version by wrapping a Scala class */ +trait WrappedAsJava[J] { + /** Returns an appropriate Java version */ + def asJava: J +} From 44643f44fd9b35e9015d021626736c44b50c4100 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Thu, 9 Jul 2015 17:52:21 -0700 Subject: [PATCH 012/340] Tests, manually written, for function converters. These were written manually to avoid making the same assumptions in code generation for the converters and the tests, and thereby missing important bugs. As a downside, though, they do not have complete code coverage. This should not matter given how the code generator works, but it is a weak point. --- README.md | 66 +- fnGen/WrapFnGen.scala | 112 +-- .../compat/java8/FunctionConvertersTest.scala | 834 ++++++++++++++++++ 3 files changed, 959 insertions(+), 53 deletions(-) create mode 100644 src/test/scala/scala/compat/java8/FunctionConvertersTest.scala diff --git a/README.md b/README.md index 2493c0c..68dcc92 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,69 @@ class Test { [More Examples / Documentation](src/test/java/scala/compat/java8/LambdaTest.java) +## Converters between `scala.FunctionN` and `java.util.function` + +A set of converters that enable interconversion between Java's standard +Functional Interfaces defined in `java.util.function` and Scala's `Function0`, +`Function1`, and `Function2` traits. These are intended for use when you +already have an instance of a `java.util.function` and need a Scala function, +or have a Scala function and need an instance of a `java.util.function`. + +The `.asScala` extension method will convert a `java.util.function` to the corresponding +Scala function. The `.asJava` extension method will convert a Scala function to +the most specific corresponding Java functional interface. If you wish to obtain +a less specific functional interface, there are named methods that start with `asJava` +and continue with the name of the Java functional interface. For instance, the +most specific interface corresponding to the Scala function `val rev = (s: String) => s.reverse` +is `UnaryOperator[String]`, and that is what `rev.asJava` will produce. However, +`asJavaFunction(rev)` will return a `java.util.function.Function[String, String]` instead. + +The `asJava` methods can also be called conveniently from Java. There are additional +`asScalaFrom` methods (e.g. `asScalaFromUnaryOperator`) that will perform the +functional-interface-to-Scala-function conversion; this is primarily of use when calling +from Java since the `.asScala` extension method is more convenient in Scala. + +#### Usage examples + +In Scala: + +```scala +import java.util.function._ +import scala.compat.java8.FunctionConverters._ + +val foo: Int => Boolean = i => i > 7 +def testBig(ip: IntPredicate) = ip.test(9) +println(testBig(foo.asJava)) // Prints true + +val bar = new UnaryOperator[String]{ def apply(s: String) = s.reverse } +List("cod", "herring").map(bar.asScala) // List("doc", "gnirrih") + +def testA[A](p: Predicate[A])(a: A) = p.test(a) +println(testA(asJavaPredicate(foo))(4)) // Prints false + +// println(testA(foo.asJava)(4)) <-- doesn't work +// IntPredicate does not extend Predicate! +``` + +In Java: + +```java +import java.util.function.*; +import scala.compat.java8.FunctionConverters; + +class Example { + String foo(UnaryOperator f) { + return f.apply("halibut"); + } + String bar(scala.Function1 f) { + return foo(functionConverters.asJavaUnaryOperator(f)); + } + String baz(Function f) { + return bar(functionConverters.asScalaFromFunction(f)); + } +} +``` + ## Converters between `scala.concurrent` and `java.util.concurrent` - [API](src/main/scala/scala/compat/java8/FutureConverters.scala) @@ -53,6 +116,7 @@ class Test { } ``` + ## Future work - - Converters for `java.util.function`, `java.util.stream` + - Converters for `java.util.stream` - [`Spliterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html)s for Scala collections diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 7ee0b4c..02938f5 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -10,9 +10,9 @@ object WrapFnGen { | * This file auto-generated by WrapFnGen.scala. Do not modify directly. | */ |""".stripMargin - + val packaging = "package scala.compat.java8" - + import scala.tools.nsc._ import scala.reflect.internal._ val settings = new Settings(msg => sys.error(msg)) @@ -21,12 +21,12 @@ object WrapFnGen { val run = new compiler.Run import compiler._, definitions._ - - + + implicit class IndentMe(v: Vector[String]) { def indent: Vector[String] = v.map(" " + _) } - + implicit class FlattenMe(v: Vector[Vector[String]]) { def mkVec(join: String = ""): Vector[String] = { val vb = Vector.newBuilder[String] @@ -39,7 +39,7 @@ object WrapFnGen { vb.result() } } - + implicit class DoubleFlattenMe(v: Vector[Vector[Vector[String]]]) { def mkVecVec(join: String = ""): Vector[String] = { val vb = Vector.newBuilder[String] @@ -57,23 +57,24 @@ object WrapFnGen { vb.result() } } - + implicit class SplitMyLinesAndStuff(s: String) { def toVec = s.linesIterator.toVector def nonBlank = s.trim.length > 0 } - + implicit class TreeToText(t: Tree) { def text = showCode(t).replace("$", "").linesIterator.toVector } - + case class Prioritized(lines: Vector[String], priority: Int) { def withPriority(i: Int) = copy(priority = i) } - + case class SamConversionCode( base: String, wrappedAsScala: Vector[String], + asScalaAnyVal: Vector[String], implicitToScala: Vector[String], asScalaDef: Vector[String], wrappedAsJava: Vector[String], @@ -81,15 +82,14 @@ object WrapFnGen { implicitToJava: Prioritized, asJavaDef: Vector[String] ) { - def impls: Vector[Vector[String]] = Vector(wrappedAsScala, wrappedAsJava, asJavaAnyVal) + def impls: Vector[Vector[String]] = Vector(wrappedAsScala, asScalaAnyVal, wrappedAsJava, asJavaAnyVal) def defs: Vector[Vector[String]] = Vector(asScalaDef, asJavaDef) - def convs: Vector[Vector[String]] = Vector(implicitToScala, implicitToJava.lines) def withPriority(i: Int): SamConversionCode = copy(implicitToJava = implicitToJava.withPriority(i)) } object SamConversionCode { def apply(scc: SamConversionCode*): (Vector[String], Vector[Vector[String]]) = { val sccDepthSet = scc.map(_.implicitToJava.priority).toSet - val codes = + val codes = { if (sccDepthSet != (0 to sccDepthSet.max).toSet) { val sccDepthMap = sccDepthSet.toList.sorted.zipWithIndex.toMap @@ -98,21 +98,21 @@ object WrapFnGen { else scc }.toVector.sortBy(_.base) def priorityName(n: Int, pure: Boolean = false): String = { - val pre = + val pre = if (n <= 0) - if (pure) "functionConverters" + if (pure) "FunctionConverters" else s"package object ${priorityName(n, pure = true)}" else if (pure) s"Priority${n}FunctionConverters" else s"trait ${priorityName(n, pure = true)}" - if (!pure && n < sccDepthSet.size) s"$pre extends ${priorityName(n+1, pure = true)}" else pre + if (!pure && n < (sccDepthSet.size-1)) s"$pre extends ${priorityName(n+1, pure = true)}" else pre } - val impls = + val impls = "package functionConverterImpls {" +: { codes.map(_.impls).mkVecVec().indent } :+ "}" val traits = codes.filter(_.implicitToJava.priority > 0).groupBy(_.implicitToJava.priority).toVector.sortBy(- _._1).map{ case (k,vs) => - s"trait Priority${k}FunctionConverters {" +: + s"${priorityName(k)} {" +: s" import functionConverterImpls._" +: s" " +: vs.map(_.implicitToJava.lines).mkVec().indent :+ @@ -120,21 +120,24 @@ object WrapFnGen { } val explicitDefs = codes.map(_.defs).mkVecVec() val packageObj = - s"${priorityName(0)} {" +: + s"${priorityName(0)} {" +: s" import functionConverterImpls._" +: s" " +: { explicitDefs.indent ++ - codes.filter(_.implicitToJava.priority == 0).map(_.convs).mkVecVec().indent + Vector.fill(3)(" ") ++ + codes.filter(_.implicitToJava.priority == 0).map(_.implicitToJava.lines).mkVec().indent ++ + Vector.fill(3)(" ") ++ + codes.map(_.implicitToScala).mkVec().indent } :+ "}" (impls, traits :+ packageObj) } } - + private def buildWrappersViaReflection: Seq[SamConversionCode] = { val pack: Symbol = rootMirror.getPackageIfDefined(TermName("java.util.function")) - + case class Jfn(iface: Symbol, sam: Symbol) { lazy val genericCount = iface.typeParams.length lazy val name = sam.name.toTermName @@ -145,14 +148,14 @@ object WrapFnGen { lazy val rType = sig.resultType def arity = params.length } - + val sams = pack.info.decls. map(d => (d, d.typeSignature.members.filter(_.isAbstract).toList)). collect{ case (d, m :: Nil) if d.isAbstract => Jfn(d, m) } - + def generate(jfn: Jfn): SamConversionCode = { def mkRef(tp: Type): Tree = if (tp.typeSymbol.isTypeParameter) Ident(tp.typeSymbol.name.toTypeName) else tq"$tp" - + // Types for the Java SAM and the corresponding Scala function, plus all type parameters val scalaType = gen.mkAttributedRef(FunctionClass(jfn.arity)) val javaType = gen.mkAttributedRef(jfn.iface) @@ -160,62 +163,66 @@ object WrapFnGen { val tdParams: List[TypeDef] = tnParams.map(TypeDef(NoMods, _, Nil, EmptyTree)) val javaTargs: List[Tree] = tdParams.map(_.name).map(Ident(_)) val scalaTargs: List[Tree] = jfn.pTypes.map(mkRef) :+ mkRef(jfn.rType) - + // Conversion wrappers have three or four components that we need to name // (1) The wrapper class that wraps a Java SAM as Scala function, or vice versa (ClassN) // (2) A value class that provides .asJava or .asScala to request the conversion (ValCN) // (3) A name for an explicit conversion method (DefN) - // (4) If nested-trait lookup is needed to pick types, an implicit conversion method name (ImpN) - + // (4) An implicit conversion method name (ImpN) that invokes the value class + // Names for Java conversions to Scala val j2sClassN = TypeName("FromJava" + jfn.title) val j2sValCN = TypeName("Rich" + jfn.title + "As" + scalaType.name.encoded) val j2sDefN = TermName("asScalaFrom" + jfn.title) - + val j2sImpN = TermName("enrichAsScalaFrom" + jfn.title) + // Names for Scala conversions to Java val s2jClassN = TypeName("AsJava" + jfn.title) val s2jValCN = TypeName("Rich" + scalaType.name.encoded + "As" + jfn.title) val s2jDefN = TermName("asJava" + jfn.title) val s2jImpN = TermName("enrichAsJava" + jfn.title) - + // Argument lists for the function / SAM - val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) => + val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) => ValDef(NoMods, p.name.toTermName, if (t.typeSymbol.isTypeParameter) Ident(t.typeSymbol.name) else gen.mkAttributedRef(t.typeSymbol), EmptyTree) } val vParamRefs = vParams.map(_.name).map(Ident(_)) - - val j2sClassTree = + + val j2sClassTree = q"""class $j2sClassN[..$tdParams](jf: $javaType[..$javaTargs]) extends $scalaType[..$scalaTargs] { def apply(..$vParams) = jf.${jfn.name}(..$vParamRefs) }""" - + val j2sValCTree = - q"""implicit class $j2sValCN[..$tdParams](private val underlying: $javaType[..$javaTargs]) extends AnyVal { + q"""class $j2sValCN[..$tdParams](private val underlying: $javaType[..$javaTargs]) extends AnyVal { @inline def asScala: $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](underlying) }""" - + val j2sDefTree = - q"""def $j2sDefN[..$tdParams](jf: $javaType[..$javaTargs]): $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](jf)""" - + q"""@inline def $j2sDefN[..$tdParams](jf: $javaType[..$javaTargs]): $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](jf)""" + + val j2sImpTree = + q"""@inline implicit def $j2sImpN[..$tdParams](jf: $javaType[..$javaTargs]): $j2sValCN[..$tnParams] = new $j2sValCN[..$tnParams](jf)""" + val s2jClassTree = q"""class $s2jClassN[..$tdParams](sf: $scalaType[..$scalaTargs]) extends $javaType[..$javaTargs] { def ${jfn.name}(..$vParams) = sf.apply(..$vParamRefs) }""" - + val s2jValCTree = q"""class $s2jValCN[..$tdParams](private val underlying: $scalaType[..$scalaTargs]) extends AnyVal { @inline def asJava: $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](underlying) }""" - + val s2jDefTree = - q"""def $s2jDefN[..$tdParams](sf: $scalaType[..$scalaTargs]): $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](sf)""" - + q"""@inline def $s2jDefN[..$tdParams](sf: $scalaType[..$scalaTargs]): $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](sf)""" + // This is especially tricky because functions are contravariant in their arguments // Need to prevent e.g. Any => String from "downcasting" itself to Int => String; we want the more exact conversion val s2jImpTree: (Tree, Int) = if (jfn.pTypes.forall(! _.isFinalType) && jfn.sig == jfn.sam.typeSignature) ( - q"""implicit def $s2jImpN[..$tdParams](sf: $scalaType[..$scalaTargs]): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf)""", + q"""@inline implicit def $s2jImpN[..$tdParams](sf: $scalaType[..$scalaTargs]): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf)""", tdParams.length ) else { @@ -242,18 +249,19 @@ object WrapFnGen { map(TypeDef(NoMods, _, Nil, EmptyTree)). dropRight(if (jfn.rType.isFinalType) 1 else 0) val evs = evidences.map{ case (generic, specific) => ValDef(NoMods, TermName("ev"+generic.toString), tq"$generic =:= $specific", EmptyTree) } - val tree = - q"""implicit def $s2jImpN[..$scalafnTdefs](sf: $scalaType[..$scalafnTnames])(implicit ..$evs): $s2jValCN[..$tnParams] = + val tree = + q"""@inline implicit def $s2jImpN[..$scalafnTdefs](sf: $scalaType[..$scalafnTnames])(implicit ..$evs): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf.asInstanceOf[$scalaType[..$scalaTargs]]) """ val depth = numberedA.size (tree, tdParams.length) } - + SamConversionCode( base = jfn.title, wrappedAsScala = j2sClassTree.text, - implicitToScala = j2sValCTree.text, + asScalaAnyVal = j2sValCTree.text, + implicitToScala = j2sImpTree.text, asScalaDef = j2sDefTree.text, wrappedAsJava = s2jClassTree.text, asJavaAnyVal = s2jValCTree.text, @@ -261,10 +269,10 @@ object WrapFnGen { asJavaDef = s2jDefTree.text ) } - + sams.toSeq.map(generate) } - + lazy val converterContents = s""" |$copyright @@ -278,13 +286,13 @@ object WrapFnGen { (SamConversionCode(buildWrappersViaReflection: _*) match { case (impls, defs) => impls.mkString("\n") + "\n\n\n\n" + defs.map(_.mkString("\n")).mkString("\n\n\n\n") }) - + def sameText(f: java.io.File, text: String): Boolean = { val x = scala.io.Source.fromFile(f) val lines = try { x.getLines.toVector } finally { x.close } lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) } - + def write(f: java.io.File, text: String) { if (!f.exists || !sameText(f, text)) { val p = new java.io.PrintWriter(f) @@ -292,7 +300,7 @@ object WrapFnGen { finally { p.close() } } } - + def main(args: Array[String]) { val names = args.iterator.map(x => new java.io.File(x)) write(names.next, converterContents) diff --git a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala new file mode 100644 index 0000000..7e8f76d --- /dev/null +++ b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala @@ -0,0 +1,834 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class FunctionConvertersTest { + import java.io.File + import java.util.function._ + import FunctionConverters._ + + val str = "fish" + val fyl = new File("salmon") + val num = 42 + val nmm = 9L + val nnn = 0.3 + + var cache: Any = null + def save(a: Any) = { cache = a; a } + def recall = { val ans = cache; cache = null; ans } + + case class Box[A](value: A) {} + + def sameS[A,B,C,D,E,F](f: (A, B) => C, g: (D, E) => F)(implicit ev1: A =:= D, ev2: B =:= E, ev3: C =:= F): Box[(A,B) => Boolean] = + Box((a: A, b: B) => f(a,b) == g(ev1(a),ev2(b))) + + def sameS[A,B,C,D](f: A => B, g: C => D)(implicit ev1: A =:= C, ev2: B =:= D): Box[A => Boolean] = + Box((a: A) => f(a) == g(ev1(a))) + + // BiConsumer tests; conceptually widens to BiFunction, narrows to ObjLongConsumer + @Test + def test_BiConsumer() { + val bic1 = new BiConsumer[String, File]{ def accept(s: String, f: File) { save((s,f)) } } + val bic2 = new BiConsumer[Int, Long]{ def accept(i: Int, l: Long) { save((i,l)) } } + val sbic = (s: String, f: File) => { save((s,f)); () } + val zbic = (i: Int, l: Long) => { save((i,l)); () } + def jbic[A, B](bic: BiConsumer[A, B])(a: A, b: B) = { bic.accept(a,b); recall == (a,b) } + def fbic[A, B](f: (A,B) => Unit)(a: A, b: B) = { f(a,b); recall == (a,b) } + assert(jbic(asJavaBiConsumer(sbic))(str, fyl)) + assert(jbic(asJavaBiConsumer(zbic))(num, nmm)) + assert(jbic(sbic.asJava)(str, fyl)) + // assert(jbic(zbic.asJava)(num, nmm)) -- ObjLongConsumer + assert(fbic(asScalaFromBiConsumer(bic1))(str, fyl)) + assert(fbic(asScalaFromBiConsumer(bic2))(num, nmm)) + assert(fbic(bic1.asScala)(str, fyl)) + assert(fbic(bic2.asScala)(num, nmm)) + } + + + // BiFunction tests; conceptually narrows to any of the Bi functions or to ObjLongConsumer etc + @Test + def test_BiFunction { + val bif1 = new BiFunction[String, File, (String, File)]{ def apply(s: String, f: File) = (s,f) } + val bif2 = new BiFunction[Int, Long, Double]{ def apply(i: Int, l: Long) = i.toDouble*l } + val sbif = (s: String, f: File) => (s,f) + val zbif = (i: Int, l: Long) => i.toDouble*l + def sameJ[A,B,C,D,E,F](f: BiFunction[A, B, C], g: BiFunction[D, E, F])(implicit ev1: A =:= D, ev2: B =:= E, ev3: C =:= F) = + Box((a: A, b: B) => f.apply(a,b) == g.apply(ev1(a), ev2(b))) + assert(sameJ(bif1, sbif.asJava).value(str,fyl)) + assert(sameJ(bif1, asJavaBiFunction(sbif)).value(str,fyl)) + // assert(sameJ(bif2, zbif.asJava)) -- ToDoubleBiFunction + assert(sameJ(bif2, asJavaBiFunction(zbif)).value(num,nmm)) + assert(sameS(bif1.asScala, sbif).value(str,fyl)) + assert(sameS(asScalaFromBiFunction(bif1), sbif).value(str,fyl)) + assert(sameS(bif2.asScala, zbif).value(num,nmm)) + assert(sameS(asScalaFromBiFunction(bif2), zbif).value(num,nmm)) + } + + // BinaryOperator tests; actually widens to BiFunction and conceptually narrows to IntBinaryOperator etc. + @Test + def test_BinaryOperator { + val bop1 = new BinaryOperator[String]{ def apply(s: String, t: String) = s + t } + val bop2 = new BinaryOperator[Int]{ def apply(i: Int, j: Int) = i + j } + val sbop = (s: String, t: String) => s + t + val zbop = (i: Int, j: Int) => i + j + def sameJ[A,B](f: BinaryOperator[A], g: BinaryOperator[B])(implicit ev1: A =:= B) = + Box((a1: A, a2: A) => f.apply(a1, a2) == g.apply(ev1(a1), ev1(a2))) + assert(sameJ(bop1, sbop.asJava).value(str,str)) + assert(sameJ(bop1, asJavaBinaryOperator(sbop)).value(str,str)) + // assert(sameJ(bop2, zbop.asJava).value(num, num)) -- IntBinaryOperator + assert(sameJ(bop2, asJavaBinaryOperator(zbop)).value(num,num)) + assert(sameS(bop1.asScala, sbop).value(str,str)) + assert(sameS(asScalaFromBinaryOperator(bop1), sbop).value(str,str)) + assert(sameS(bop2.asScala, zbop).value(num,num)) + assert(sameS(asScalaFromBinaryOperator(bop2), zbop).value(num,num)) + } + + // BiPredicate tests; conceptually widens to BiFunction. Does not narrow (no IntBiPredicate or the like). + @Test + def test_BiPredicate { + val bip1 = new BiPredicate[String, File]{ def test(s: String, f: File) = s == f.getName } + val bip2 = new BiPredicate[Int, Long]{ def test(i: Int, l: Long) = i == l } + val sbip = (s: String, f: File) => s == f.getName + val zbip = (i: Int, l: Long) => i == l + def sameJ[A,B,C,D](f: BiPredicate[A,B], g: BiPredicate[C,D])(implicit ev1: A =:= C, ev2: B =:= D) = + Box((a: A, b: B) => f.test(a,b) == g.test(ev1(a), ev2(b))) + assert(sameJ(bip1, sbip.asJava).value(str,fyl)) + assert(sameJ(bip1, asJavaBiPredicate(sbip)).value(str,fyl)) + assert(sameJ(bip2, zbip.asJava).value(num,nmm)) + assert(sameJ(bip2, asJavaBiPredicate(zbip)).value(num, nmm)) + assert(sameS(bip1.asScala, sbip).value(str,fyl)) + assert(sameS(asScalaFromBiPredicate(bip1), sbip).value(str,fyl)) + assert(sameS(bip2.asScala, zbip).value(num, nmm)) + assert(sameS(asScalaFromBiPredicate(bip2), zbip).value(num,nmm)) + } + + // BooleanSupplier tests; conceptually widens to Supplier and Function. + @Test + def test_BooleanSupplier { + val bsup = new BooleanSupplier{ def getAsBoolean = true } + val sbup = () => true + def foo(bs: BooleanSupplier) = bs.getAsBoolean + def bar(f: () => Boolean) = foo(f.asJava) + def baz(bs: BooleanSupplier) = bar(bs.asScala) + assertEquals(foo(bsup), bar(sbup)) + assertEquals(foo(bsup), baz(bsup)) + assertEquals(foo(bsup), bar(asScalaFromBooleanSupplier(bsup))) + assertEquals(foo(bsup), baz(asJavaBooleanSupplier(sbup))) + } + + // Consumer tests; conceptually widens to Function and narrows to IntConsumer etc. + @Test + def test_Consumer { + val con1 = new Consumer[String]{ def accept(s: String) { save(s) } } + val con2 = new Consumer[Int]{ def accept(i: Int) { save(i) } } + val scon = (s: String) => { save(s); () } + val zcon = (i: Int) => { save(i); () } + def jcon[A](c: Consumer[A])(a: A) = { c.accept(a); recall == a } + def fcon[A](f: A => Unit)(a: A) = { f(a); recall == a } + assert(jcon(scon.asJava)(str)) + assert(jcon(asJavaConsumer(scon))(str)) + // assert(jcon(zcon.asJava)) -- IntConsumer + assert(jcon(asJavaConsumer(zcon))(num)) + assert(fcon(con1.asScala)(str)) + assert(fcon(asScalaFromConsumer(con1))(str)) + assert(fcon(con2.asScala)(num)) + assert(fcon(asScalaFromConsumer(con2))(num)) + } + + // DoubleBinaryOperator tests; conceptually widens to BinaryOperator, ToDoubleBiFunction, and BiFunction + @Test + def test_DoubleBinaryOperator { + val dbop = new DoubleBinaryOperator{ def applyAsDouble(a: Double, b: Double) = a*b } + val sdbo = (a: Double, b: Double) => a*b + def foo(dbo: DoubleBinaryOperator)(a: Double, b: Double) = dbo.applyAsDouble(a,b) + def bar(f: (Double, Double) => Double)(a: Double, b: Double) = foo(f.asJava)(a,b) + def baz(dbo: DoubleBinaryOperator)(a: Double, b: Double) = bar(dbo.asScala)(a,b) + assertEquals(foo(dbop)(nnn, nnn), bar(sdbo)(nnn, nnn), 1e-9) + assertEquals(foo(dbop)(nnn, nnn), baz(dbop)(nnn, nnn), 1e-9) + assertEquals(foo(dbop)(nnn, nnn), bar(asScalaFromDoubleBinaryOperator(dbop))(nnn, nnn), 1e-9) + assertEquals(foo(dbop)(nnn, nnn), baz(asJavaDoubleBinaryOperator(sdbo))(nnn, nnn), 1e-9) + } + + // DoubleConsumer tests; conceptually widens to Consumer and Function + @Test + def test_DoubleConsumer { + val dcon = new DoubleConsumer{ def accept(value: Double) { save(value) } } + val sdco = (d: Double) => { save(d); () } + def jf(dc: DoubleConsumer)(d: Double) = { dc.accept(d); recall == d } + def sf(f: Double => Unit)(d: Double) = { f(d); recall == d } + assert(jf(sdco.asJava)(nnn)) + assert(jf(asJavaDoubleConsumer(sdco))(nnn)) + assert(sf(dcon.asScala)(nnn)) + assert(sf(asScalaFromDoubleConsumer(dcon))(nnn)) + } + + // DoubleFunction tests; conceptually widens to Function, narrows to DoubleUnaryOperator and DoubleToIntFunction etc. + @Test + def test_DoubleFunction { + val dfn1 = new DoubleFunction[String]{ def apply(value: Double) = f"$value%.3f" } + val dfn2 = new DoubleFunction[Int]{ def apply(value: Double) = math.ceil(value).toInt } + val sdfn = (d: Double) => f"$d%.3f" + val zdfn = (d: Double) => math.ceil(d).toInt + assertEquals(dfn1(nnn), sdfn(nnn)) + assertEquals(dfn1(nnn), dfn1.asScala(nnn)) + assertEquals(dfn1(nnn), asScalaFromDoubleFunction(dfn1)(nnn)) + assertEquals(dfn1(nnn), sdfn.asJava(nnn)) + assertEquals(dfn1(nnn), asJavaDoubleFunction(sdfn)(nnn)) + assertEquals(dfn2(nnn), zdfn(nnn)) + assertEquals(dfn2(nnn), dfn2.asScala(nnn)) + assertEquals(dfn2(nnn), asScalaFromDoubleFunction(dfn2)(nnn)) + /// assertEquals(dfn2(nnn), zdfn.asJava(nnn)) -- DoubleToIntFunction + assertEquals(dfn2(nnn), asJavaDoubleFunction(zdfn)(nnn)) + } + + // DoublePredicate tests; conceptually widens to DoubleFunction, Predicate, and Function + @Test + def test_DoublePredicate { + val dprd = new DoublePredicate{ def test(value: Double) = value > 0 } + val sdpr = (d: Double) => d > 0 + def foo(dp: DoublePredicate)(d: Double) = dp.test(d) + def bar(f: Double => Boolean)(d: Double) = foo(f.asJava)(d) + def baz(dp: DoublePredicate)(d: Double) = bar(dp.asScala)(d) + assertEquals(foo(dprd)(nnn), bar(sdpr)(nnn)) + assertEquals(foo(dprd)(nnn), baz(dprd)(nnn)) + assertEquals(foo(dprd)(nnn), bar(asScalaFromDoublePredicate(dprd))(nnn)) + assertEquals(foo(dprd)(nnn), baz(asJavaDoublePredicate(sdpr))(nnn)) + } + + // DoubleSupplier tests; conceptually widens to Supplier and Function + @Test + def test_DoubleSupplier { + val dsup = new DoubleSupplier{ def getAsDouble = 22.0/7 } + val sdsu = () => 22.0/7 + def foo(ds: DoubleSupplier) = ds.getAsDouble + def bar(f: () => Double) = foo(f.asJava) + def baz(ds: DoubleSupplier) = bar(ds.asScala) + assertEquals(foo(dsup), bar(sdsu), 1e-9) + assertEquals(foo(dsup), baz(dsup), 1e-9) + assertEquals(foo(dsup), bar(asScalaFromDoubleSupplier(dsup)), 1e-9) + assertEquals(foo(dsup), baz(asJavaDoubleSupplier(sdsu)), 1e-9) + } + + // DoubleToIntFunction tests; conceptually widens to DoubleFunction and Function + @Test + def test_DoubleToIntFunction { + val d2if = new DoubleToIntFunction{ def applyAsInt(value: Double) = math.ceil(value).toInt } + val sd2i = (d: Double) => math.ceil(d).toInt + def foo(di: DoubleToIntFunction)(d: Double) = di.applyAsInt(d) + def bar(f: Double => Int)(d: Double) = foo(f.asJava)(d) + def baz(di: DoubleToIntFunction)(d: Double) = bar(di.asScala)(d) + assertEquals(foo(d2if)(nnn), bar(sd2i)(nnn)) + assertEquals(foo(d2if)(nnn), baz(d2if)(nnn)) + assertEquals(foo(d2if)(nnn), bar(asScalaFromDoubleToIntFunction(d2if))(nnn)) + assertEquals(foo(d2if)(nnn), baz(asJavaDoubleToIntFunction(sd2i))(nnn)) + } + + // DoubleToLongFunction tests; conceptually widens to DoubleFunction and Function + @Test + def test_DoubleToLongFunction { + val d2lf = new DoubleToLongFunction{ def applyAsLong(value: Double) = java.lang.Double.doubleToRawLongBits(value) } + val sd2l = (d: Double) => java.lang.Double.doubleToRawLongBits(d) + def foo(dl: DoubleToLongFunction)(d: Double) = dl.applyAsLong(d) + def bar(f: Double => Long)(d: Double) = foo(f.asJava)(d) + def baz(dl: DoubleToLongFunction)(d: Double) = bar(dl.asScala)(d) + assertEquals(foo(d2lf)(nnn), bar(sd2l)(nnn)) + assertEquals(foo(d2lf)(nnn), baz(d2lf)(nnn)) + assertEquals(foo(d2lf)(nnn), bar(asScalaFromDoubleToLongFunction(d2lf))(nnn)) + assertEquals(foo(d2lf)(nnn), baz(asJavaDoubleToLongFunction(sd2l))(nnn)) + } + + // DoubleUnaryOperator tests; conceptually widens to DoubleFunction and ToDoubleFunction and Function + @Test + def test_DoubleUnaryOperator { + val duop = new DoubleUnaryOperator{ def applyAsDouble(value: Double) = 1.0 - value } + val sduo = (d: Double) => 1.0 - d + def foo(du: DoubleUnaryOperator)(d: Double) = du.applyAsDouble(d) + def bar(f: Double => Double)(d: Double) = foo(f.asJava)(d) + def baz(du: DoubleUnaryOperator)(d: Double) = bar(du.asScala)(d) + assertEquals(foo(duop)(nnn), bar(sduo)(nnn), 1e-9) + assertEquals(foo(duop)(nnn), baz(duop)(nnn), 1e-9) + assertEquals(foo(duop)(nnn), bar(asScalaFromDoubleUnaryOperator(duop))(nnn), 1e-9) + assertEquals(foo(duop)(nnn), baz(asJavaDoubleUnaryOperator(sduo))(nnn), 1e-9) + } + + // Function tests; conceptually narrows to everything except BiFunction and its conceptual subclasses + @Test + def test_Function { + val fun1 = new Function[String, File]{ def apply(s: String): File = new File(s) } + val fun2 = new Function[Int, Long]{ def apply(i: Int): Long = ((i.toLong)<<32) | i } + def sfun = (s: String) => new File(s) + def zfun = (i: Int) => (i.toLong << 32) | i + def jf1(f: Function[String, File])(s: String) = f.apply(s) + def jf2(f: Function[Int, Long])(i: Int) = f.apply(i) + def sf1(f: String => File)(s: String) = f(s) + def sf2(f: Int => Long)(i: Int) = f(i) + val ans = fun1(str) + assertEquals(ans, sfun(str)) + assertEquals(ans, jf1(fun1)(str)) + assertEquals(ans, sf1(sfun)(str)) + assertEquals(ans, jf1(sfun.asJava)(str)) + assertEquals(ans, sf1(fun1.asScala)(str)) + assertEquals(ans, jf1(asJavaFunction(sfun))(str)) + assertEquals(ans, sf1(asScalaFromFunction(fun1))(str)) + val anz = fun2(num) + assertEquals(anz, zfun(num)) + assertEquals(anz, jf2(fun2)(num)) + assertEquals(anz, sf2(zfun)(num)) + // assertEquals(anz, jf2(zfun.asJava)(num)) -- IntToLongFunction + assertEquals(anz, sf2(fun2.asScala)(num)) + assertEquals(anz, jf2(asJavaFunction(zfun))(num)) + assertEquals(anz, sf2(asScalaFromFunction(fun2))(num)) + } + + // IntBinaryOperator tests; conceptually widens to BinaryOperator, ToIntBiFunction, and BiFunction + @Test + def test_IntBinaryOperator { + val ibop = new IntBinaryOperator{ def applyAsInt(a: Int, b: Int) = a ^ b } + val sibo = (i: Int, j: Int) => i ^ j + def foo(ibo: IntBinaryOperator)(a: Int, b: Int) = ibo.applyAsInt(a,b) + def bar(f: (Int, Int) => Int)(a: Int, b: Int) = foo(f.asJava)(a,b) + def baz(ibo: IntBinaryOperator)(a: Int, b: Int) = bar(ibo.asScala)(a,b) + assertEquals(foo(ibop)(num, num), bar(sibo)(num, num)) + assertEquals(foo(ibop)(num, num), baz(ibop)(num, num)) + assertEquals(foo(ibop)(num, num), bar(asScalaFromIntBinaryOperator(ibop))(num, num)) + assertEquals(foo(ibop)(num, num), baz(asJavaIntBinaryOperator(sibo))(num, num)) + } + + // IntConsumer tests; conceptually widens to Consumer and Function + @Test + def test_IntConsumer { + val icon = new IntConsumer{ def accept(i: Int) { save(i) } } + val sico = (i: Int) => { save(i); () } + def jf(ic: IntConsumer)(d: Int) = { ic.accept(d); recall == d } + def sf(f: Int => Unit)(d: Int) = { f(d); recall == d } + assert(jf(sico.asJava)(num)) + assert(jf(asJavaIntConsumer(sico))(num)) + assert(sf(icon.asScala)(num)) + assert(sf(asScalaFromIntConsumer(icon))(num)) + } + + // IntFunction tests; conceptually widens to Function + @Test + def test_IntFunction { + val ifn1 = new IntFunction[String]{ def apply(i: Int) = "!"*i } + val ifn2 = new IntFunction[Long]{ def apply(i: Int) = ((i.toLong) << 32) | i } + val sifn = (i: Int) => "!"*i + val zifn = (i: Int) => (i.toLong << 32) | i + assertEquals(ifn1(num), sifn(num)) + assertEquals(ifn1(num), ifn1.asScala(num)) + assertEquals(ifn1(num), asScalaFromIntFunction(ifn1)(num)) + assertEquals(ifn1(num), sifn.asJava(num)) + assertEquals(ifn1(num), asJavaIntFunction(sifn)(num)) + assertEquals(ifn2(num), zifn(num)) + assertEquals(ifn2(num), ifn2.asScala(num)) + assertEquals(ifn2(num), asScalaFromIntFunction(ifn2)(num)) + /// assertEquals(ifn2(num), zifn.asJava(num)) -- IntToLongFunction + assertEquals(ifn2(num), asJavaIntFunction(zifn)(num)) + } + + // IntPredicate tests; conceptually widens to IntFunction, Predicate, and Function + @Test + def test_IntPredicate { + val iprd = new IntPredicate{ def test(i: Int) = i < 0 } + val sipr = (i: Int) => i < 0 + def foo(ip: IntPredicate)(d: Int) = ip.test(d) + def bar(f: Int => Boolean)(d: Int) = foo(f.asJava)(d) + def baz(ip: IntPredicate)(d: Int) = bar(ip.asScala)(d) + assertEquals(foo(iprd)(num), bar(sipr)(num)) + assertEquals(foo(iprd)(num), baz(iprd)(num)) + assertEquals(foo(iprd)(num), bar(asScalaFromIntPredicate(iprd))(num)) + assertEquals(foo(iprd)(num), baz(asJavaIntPredicate(sipr))(num)) + } + + // IntSupplier tests; conceptually widens to Supplier and Function + @Test + def test_IntSupplier { + val isup = new IntSupplier{ def getAsInt = 42 } + val sisu = () => 42 + def foo(ds: IntSupplier) = ds.getAsInt + def bar(f: () => Int) = foo(f.asJava) + def baz(ds: IntSupplier) = bar(ds.asScala) + assertEquals(foo(isup), bar(sisu)) + assertEquals(foo(isup), baz(isup)) + assertEquals(foo(isup), bar(asScalaFromIntSupplier(isup))) + assertEquals(foo(isup), baz(asJavaIntSupplier(sisu))) + } + + // IntToDoubleFunction tests; conceptually widens to ToDoubleFunction, IntFunction, and Function + @Test + def test_IntToDoubleFunction { + val i2df = new IntToDoubleFunction{ def applyAsDouble(i: Int) = i + 0.1*i } + def si2d = (i: Int) => i + 0.1*i + def foo(id: IntToDoubleFunction)(i: Int) = id.applyAsDouble(i) + def bar(f: Int => Double)(i: Int) = foo(f.asJava)(i) + def baz(id: IntToDoubleFunction)(i: Int) = bar(id.asScala)(i) + assertEquals(foo(i2df)(num), bar(si2d)(num), 1e-9) + assertEquals(foo(i2df)(num), baz(i2df)(num), 1e-9) + assertEquals(foo(i2df)(num), bar(asScalaFromIntToDoubleFunction(i2df))(num), 1e-9) + assertEquals(foo(i2df)(num), baz(asJavaIntToDoubleFunction(si2d))(num), 1e-9) + } + + // IntToLongFunction tests; conceptually widens to ToLongFunction, IntFunction, and Function + @Test + def test_IntToLongFunction { + val i2lf = new IntToLongFunction { def applyAsLong(i: Int) = (i.toLong << 32) | i } + val si2l = (i: Int) => (i.toLong << 32) | i + def foo(il: IntToLongFunction)(d: Int) = il.applyAsLong(d) + def bar(f: Int => Long)(d: Int) = foo(f.asJava)(d) + def baz(il: IntToLongFunction)(d: Int) = bar(il.asScala)(d) + assertEquals(foo(i2lf)(num), bar(si2l)(num)) + assertEquals(foo(i2lf)(num), baz(i2lf)(num)) + assertEquals(foo(i2lf)(num), bar(asScalaFromIntToLongFunction(i2lf))(num)) + assertEquals(foo(i2lf)(num), baz(asJavaIntToLongFunction(si2l))(num)) + } + + // IntUnaryOperator tests; conceptually widens to ToIntFunction, IntFunction, and Function + @Test + def test_IntUnaryOperator { + val iuop = new IntUnaryOperator{ def applyAsInt(i: Int) = ~i } + val siuo = (i: Int) => ~i + def foo(iu: IntUnaryOperator)(d: Int) = iu.applyAsInt(d) + def bar(f: Int => Int)(d: Int) = foo(f.asJava)(d) + def baz(iu: IntUnaryOperator)(d: Int) = bar(iu.asScala)(d) + assertEquals(foo(iuop)(num), bar(siuo)(num)) + assertEquals(foo(iuop)(num), baz(iuop)(num)) + assertEquals(foo(iuop)(num), bar(asScalaFromIntUnaryOperator(iuop))(num)) + assertEquals(foo(iuop)(num), baz(asJavaIntUnaryOperator(siuo))(num)) + } + + // LongBinaryOperator tests; conceptually widens to ToLongFunction, LongFunction, and Function + @Test + def test_LongBinaryOperator{ + val lbop = new LongBinaryOperator{ def applyAsLong(a: Long, b: Long) = a | b } + val slbo = (a: Long, b: Long) => a | b + def foo(lbo: LongBinaryOperator)(a: Long, b: Long) = lbo.applyAsLong(a,b) + def bar(f: (Long, Long) => Long)(a: Long, b: Long) = foo(f.asJava)(a,b) + def baz(lbo: LongBinaryOperator)(a: Long, b: Long) = bar(lbo.asScala)(a,b) + assertEquals(foo(lbop)(nmm, nmm), bar(slbo)(nmm, nmm)) + assertEquals(foo(lbop)(nmm, nmm), baz(lbop)(nmm, nmm)) + assertEquals(foo(lbop)(nmm, nmm), bar(asScalaFromLongBinaryOperator(lbop))(nmm, nmm)) + assertEquals(foo(lbop)(nmm, nmm), baz(asJavaLongBinaryOperator(slbo))(nmm, nmm)) + } + + // LongConsumer tests; conceptually widens to Consumer and Function + @Test + def test_LongConsumer { + val lcon = new LongConsumer{ def accept(l: Long) { save(l) } } + val slco = (l: Long) => { save(l); () } + def jf(lc: LongConsumer)(d: Long) = { lc.accept(d); recall == d } + def sf(f: Long => Unit)(d: Long) = { f(d); recall == d } + assert(jf(slco.asJava)(nmm)) + assert(jf(asJavaLongConsumer(slco))(nmm)) + assert(sf(lcon.asScala)(nmm)) + assert(sf(asScalaFromLongConsumer(lcon))(nmm)) + } + + // LongFunction tests; conceptually widens to Function + @Test + def test_LongFunction { + val lfn1 = new LongFunction[String]{ def apply(l: Long) = l.toString } + val lfn2 = new LongFunction[Int]{ def apply(l: Long) = (l & 0xFFFFFF).toInt } + val slfn = (l: Long) => l.toString + val zlfn = (l: Long) => (l & 0xFFFFFF).toInt + assertEquals(lfn1(nmm), slfn(nmm)) + assertEquals(lfn1(nmm), lfn1.asScala(nmm)) + assertEquals(lfn1(nmm), asScalaFromLongFunction(lfn1)(nmm)) + assertEquals(lfn1(nmm), slfn.asJava(nmm)) + assertEquals(lfn1(nmm), asJavaLongFunction(slfn)(nmm)) + assertEquals(lfn2(nmm), zlfn(nmm)) + assertEquals(lfn2(nmm), lfn2.asScala(nmm)) + assertEquals(lfn2(nmm), asScalaFromLongFunction(lfn2)(nmm)) + /// assertEquals(lfn2(nmm), zlfn.asJava(nmm)) -- LongToIntFunction + assertEquals(lfn2(nmm), asJavaLongFunction(zlfn)(nmm)) + } + + // LongPredicate tests; conceptually widens to LongFunction and Predicate and Function + @Test + def test_LongPredicate { + val lprd = new LongPredicate{ def test(l: Long) = l < 1 } + val slpr = (l: Long) => l < 1 + def foo(lp: LongPredicate)(d: Long) = lp.test(d) + def bar(f: Long => Boolean)(d: Long) = foo(f.asJava)(d) + def baz(lp: LongPredicate)(d: Long) = bar(lp.asScala)(d) + assertEquals(foo(lprd)(nmm), bar(slpr)(nmm)) + assertEquals(foo(lprd)(nmm), baz(lprd)(nmm)) + assertEquals(foo(lprd)(nmm), bar(asScalaFromLongPredicate(lprd))(nmm)) + assertEquals(foo(lprd)(nmm), baz(asJavaLongPredicate(slpr))(nmm)) + } + + // LongSupplier tests; conceptually widens to ToLongFunction and Supplier and Function + @Test + def test_LongSupplier { + val lsup = new LongSupplier{ def getAsLong = 1000000000000L } + val slsu = () => 1000000000000L + def foo(ls: LongSupplier) = ls.getAsLong + def bar(f: () => Long) = foo(f.asJava) + def baz(ls: LongSupplier) = bar(ls.asScala) + assertEquals(foo(lsup), bar(slsu)) + assertEquals(foo(lsup), baz(lsup)) + assertEquals(foo(lsup), bar(asScalaFromLongSupplier(lsup))) + assertEquals(foo(lsup), baz(asJavaLongSupplier(slsu))) + } + + // LongToDoubleFunction tests; conceptually widens to ToDoubleFunction, LongFunction, and Function + @Test + def test_LongToDoubleFunction { + val l2df = new LongToDoubleFunction{ def applyAsDouble(l: Long) = l + 1e-4*l } + def sl2d = (l: Long) => l + 1e-4*l + def foo(ld: LongToDoubleFunction)(l: Long) = ld.applyAsDouble(l) + def bar(f: Long => Double)(l: Long) = foo(f.asJava)(l) + def baz(ld: LongToDoubleFunction)(l: Long) = bar(ld.asScala)(l) + assertEquals(foo(l2df)(num), bar(sl2d)(num), 1e-9) + assertEquals(foo(l2df)(num), baz(l2df)(num), 1e-9) + assertEquals(foo(l2df)(num), bar(asScalaFromLongToDoubleFunction(l2df))(num), 1e-9) + assertEquals(foo(l2df)(num), baz(asJavaLongToDoubleFunction(sl2d))(num), 1e-9) + } + + // LongToIntFunction tests; conceptually widens to ToIntFunction, LongFunction, and Function + @Test + def test_LongToIntFunction { + val l2if = new LongToIntFunction{ def applyAsInt(l :Long) = (l & 0xFFFFFF).toInt } + val sl2i = (l: Long) => (l & 0xFFFFFF).toInt + def foo(li: LongToIntFunction)(l: Long) = li.applyAsInt(l) + def bar(f: Long => Int)(l: Long) = foo(f.asJava)(l) + def baz(li: LongToIntFunction)(l: Long) = bar(li.asScala)(l) + assertEquals(foo(l2if)(nmm), bar(sl2i)(nmm)) + assertEquals(foo(l2if)(nmm), baz(l2if)(nmm)) + assertEquals(foo(l2if)(nmm), bar(asScalaFromLongToIntFunction(l2if))(nmm)) + assertEquals(foo(l2if)(nmm), baz(asJavaLongToIntFunction(sl2i))(nmm)) + } + + // LongUnaryOperator tests; conceptually widens to LongFunction, ToLongFunction, and Function + @Test + def test_LongUnaryOperator { + val luop = new LongUnaryOperator{ def applyAsLong(l: Long) = -l } + val sluo = (l: Long) => -l + def foo(du: LongUnaryOperator)(l: Long) = du.applyAsLong(l) + def bar(f: Long => Long)(l: Long) = foo(f.asJava)(l) + def baz(du: LongUnaryOperator)(l: Long) = bar(du.asScala)(l) + assertEquals(foo(luop)(nmm), bar(sluo)(nmm)) + assertEquals(foo(luop)(nmm), baz(luop)(nmm)) + assertEquals(foo(luop)(nmm), bar(asScalaFromLongUnaryOperator(luop))(nmm)) + assertEquals(foo(luop)(nmm), baz(asJavaLongUnaryOperator(sluo))(nmm)) + } + + // ObjDoubleConsumer tests; conceptually widens to Consumer and BiFunction + @Test + def test_ObjDoubleConsumer { + val odc1 = new ObjDoubleConsumer[String]{ def accept(s: String, d: Double) { save((s,d)) } } + val odc2 = new ObjDoubleConsumer[Int]{ def accept(i: Int, d: Double) { save((i,d)) } } + val sodc = (s: String, d: Double) => { save((s,d)); () } + val zodc = (i: Int, d: Double) => { save((i,d)); () } + def jf1(odc: ObjDoubleConsumer[String])(s: String, d: Double) = { odc.accept(s,d); recall == ((s,d)) } + def jf2(odc: ObjDoubleConsumer[Int])(i: Int, d: Double) = { odc.accept(i,d); recall == ((i,d)) } + def sf1(f: (String, Double) => Unit)(s: String, d: Double) = { f(s,d); recall == ((s,d)) } + def sf2(f: (Int, Double) => Unit)(i: Int, d: Double) = { f(i,d); recall == ((i,d)) } + assert(jf1(odc1)(str, nnn)) + assert(jf1(sodc.asJava)(str, nnn)) + assert(jf1(asJavaObjDoubleConsumer(sodc))(str, nnn)) + assert(sf1(sodc)(str, nnn)) + assert(sf1(odc1.asScala)(str, nnn)) + assert(sf1(asScalaFromObjDoubleConsumer(odc1))(str, nnn)) + assert(jf2(odc2)(num, nnn)) + assert(jf2(zodc.asJava)(num, nnn)) + assert(jf2(asJavaObjDoubleConsumer(zodc))(num, nnn)) + assert(sf2(zodc)(num, nnn)) + assert(sf2(odc2.asScala)(num, nnn)) + assert(sf2(asScalaFromObjDoubleConsumer(odc2))(num, nnn)) + } + + // ObjIntConsumer tests; conceptually widens to Consumer and BiFunction + @Test + def test_ObjIntConsumer { + val oic1 = new ObjIntConsumer[String]{ def accept(s: String, i: Int) { save((s,i)) } } + val oic2 = new ObjIntConsumer[Int]{ def accept(j: Int, i: Int) { save((j,i)) } } + val soic = (s: String, i: Int) => { save((s,i)); () } + val zoic = (j: Int, i: Int) => { save((j,i)); () } + def jf1(oic: ObjIntConsumer[String])(s: String, i: Int) = { oic.accept(s,i); recall == ((s,i)) } + def jf2(oic: ObjIntConsumer[Int])(j: Int, i: Int) = { oic.accept(j,i); recall == ((j,i)) } + def sf1(f: (String, Int) => Unit)(s: String, i: Int) = { f(s,i); recall == ((s,i)) } + def sf2(f: (Int, Int) => Unit)(j: Int, i: Int) = { f(j,i); recall == ((j,i)) } + assert(jf1(oic1)(str, num)) + assert(jf1(soic.asJava)(str, num)) + assert(jf1(asJavaObjIntConsumer(soic))(str, num)) + assert(sf1(soic)(str, num)) + assert(sf1(oic1.asScala)(str, num)) + assert(sf1(asScalaFromObjIntConsumer(oic1))(str, num)) + assert(jf2(oic2)(num, num)) + assert(jf2(zoic.asJava)(num, num)) + assert(jf2(asJavaObjIntConsumer(zoic))(num, num)) + assert(sf2(zoic)(num, num)) + assert(sf2(oic2.asScala)(num, num)) + assert(sf2(asScalaFromObjIntConsumer(oic2))(num, num)) + } + + // ObjLongConsumer tests; conceptually widens to Consumer and BiFunction + @Test + def test_ObjLongConsumer { + val olc1 = new ObjLongConsumer[String]{ def accept(s: String, l: Long) { save((s,l)) } } + val olc2 = new ObjLongConsumer[Int]{ def accept(i: Int, l: Long) { save((i,l)) } } + val solc = (s: String, l: Long) => { save((s,l)); () } + val zolc = (i: Int, l: Long) => { save((i,l)); () } + def jf1(olc: ObjLongConsumer[String])(s: String, l: Long) = { olc.accept(s,l); recall == ((s,l)) } + def jf2(olc: ObjLongConsumer[Int])(i: Int, l: Long) = { olc.accept(i,l); recall == ((i,l)) } + def sf1(f: (String, Long) => Unit)(s: String, l: Long) = { f(s,l); recall == ((s,l)) } + def sf2(f: (Int, Long) => Unit)(i: Int, l: Long) = { f(i,l); recall == ((i,l)) } + assert(jf1(olc1)(str, nmm)) + assert(jf1(solc.asJava)(str, nmm)) + assert(jf1(asJavaObjLongConsumer(solc))(str, nmm)) + assert(sf1(solc)(str, nmm)) + assert(sf1(olc1.asScala)(str, nmm)) + assert(sf1(asScalaFromObjLongConsumer(olc1))(str, nmm)) + assert(jf2(olc2)(num, nmm)) + assert(jf2(zolc.asJava)(num, nmm)) + assert(jf2(asJavaObjLongConsumer(zolc))(num, nmm)) + assert(sf2(zolc)(num, nmm)) + assert(sf2(olc2.asScala)(num, nmm)) + assert(sf2(asScalaFromObjLongConsumer(olc2))(num, nmm)) + } + + // Predicate tests; conceptually widens to Function and narrows to IntPredicate etc. + @Test + def test_Predicate { + val prd1 = new Predicate[String]{ def test(s: String) = s.isEmpty } + val prd2 = new Predicate[Int]{ def test(i: Int) = i < 0 } + def sprd = (s: String) => s.isEmpty + def zprd = (i: Int) => i < 0 + def foos(p: Predicate[String])(s: String) = p.test(s) + def bars(f: String => Boolean)(s: String) = foos(f.asJava)(s) + def bazs(p: Predicate[String])(s: String) = bars(p.asScala)(s) + def fooi(p: Predicate[Int])(i: Int) = p.test(i) + def bari(f: Int => Boolean)(i: Int) = fooi(asJavaPredicate(f))(i) // .asScala gives IntPredicate + def bazi(p: Predicate[Int])(i: Int) = bari(p.asScala)(i) + assertEquals(foos(prd1)(str), bars(sprd)(str)) + assertEquals(foos(prd1)(str), bazs(prd1)(str)) + assertEquals(foos(prd1)(str), bars(asScalaFromPredicate(prd1))(str)) + assertEquals(foos(prd1)(str), bazs(asJavaPredicate(sprd))(str)) + assertEquals(fooi(prd2)(num), bari(zprd)(num)) + assertEquals(fooi(prd2)(num), bazi(prd2)(num)) + assertEquals(fooi(prd2)(num), bari(asScalaFromPredicate(prd2))(num)) + } + + // Supplier tests; conceptually widens to Function and narrows to IntSupplier etc. + @Test + def test_Supplier { + val sup1 = new Supplier[String]{ def get = "halibut" } + val sup2 = new Supplier[Int]{ def get = 17 } + val ssup = () => "halibut" + val zsup = () => 17 + def foos(s: Supplier[String]) = s.get + def bars(f: () => String) = foos(f.asJava) + def bazs(s: Supplier[String]) = bars(s.asScala) + def fooi(s: Supplier[Int]) = s.get + def bari(f: () => Int) = fooi(asJavaSupplier(f)) // .asScala gives IntSupplier + def bazi(s: Supplier[Int]) = bari(s.asScala) + val ans = foos(sup1) + assertEquals(ans, bars(ssup)) + assertEquals(ans, bazs(sup1)) + assertEquals(ans, bars(asScalaFromSupplier(sup1))) + assertEquals(ans, bazs(asJavaSupplier(ssup))) + val anz = fooi(sup2) + assertEquals(anz, bari(zsup)) + assertEquals(anz, bazi(sup2)) + assertEquals(anz, bari(asScalaFromSupplier(sup2))) + } + + // ToDoubleBiFunction tests; conceptually widens to BiFunction and narrows to DoubleBinaryOperator + @Test + def test_ToDoubleBiFunction { + { + val bfd1 = new ToDoubleBiFunction[String, File]{ def applyAsDouble(s: String, f: File) = s.length.toDouble * f.getName.length } + val sbfd = (s: String, f: File) => s.length.toDouble * f.getName.length + def jf1(tdbf: ToDoubleBiFunction[String, File])(s: String, f: File) = tdbf.applyAsDouble(s,f) + def sf1(f: (String, File) => Double)(s: String, fi: File) = f(s,fi) + val ans = jf1(bfd1)(str, fyl) + assertEquals(ans, sf1(sbfd)(str, fyl), 1e-9) + assertEquals(ans, jf1(sbfd.asJava)(str, fyl), 1e-9) + assertEquals(ans, sf1(bfd1.asScala)(str, fyl), 1e-9) + assertEquals(ans, jf1(asJavaToDoubleBiFunction(sbfd))(str, fyl), 1e-9) + assertEquals(ans, sf1(asScalaFromToDoubleBiFunction(bfd1))(str, fyl), 1e-9) + } + { + val bfd2 = new ToDoubleBiFunction[Double, File]{ def applyAsDouble(a: Double, f: File) = a * f.getName.length } + val zbfd = (a: Double, f: File) => a * f.getName.length + def jf2(tdbf: ToDoubleBiFunction[Double, File])(a: Double, f: File) = tdbf.applyAsDouble(a,f) + def sf2(f: (Double, File) => Double)(a: Double, fi: File) = f(a,fi) + val ans = jf2(bfd2)(nnn, fyl) + assertEquals(ans, sf2(zbfd)(nnn, fyl), 1e-9) + assertEquals(ans, jf2(zbfd.asJava)(nnn, fyl), 1e-9) + assertEquals(ans, sf2(bfd2.asScala)(nnn, fyl), 1e-9) + assertEquals(ans, jf2(asJavaToDoubleBiFunction(zbfd))(nnn, fyl), 1e-9) + assertEquals(ans, sf2(asScalaFromToDoubleBiFunction(bfd2))(nnn, fyl), 1e-9) + } + } + + + // ToDoubleFunction tests; conceptually widens to Function and narrows to DoubleUnaryOperator, IntToDoubleFunction, etc. + @Test + def test_ToDoubleFunction { + { + val fnd1 = new ToDoubleFunction[String]{ def applyAsDouble(s: String) = s.length / (s.headOption.getOrElse(0: Char)+1).toDouble } + val sfnd = (s: String) => s.length / (s.headOption.getOrElse(0: Char)+1).toDouble + def jf1(tdf: ToDoubleFunction[String])(s: String) = tdf.applyAsDouble(s) + def sf1(f: String => Double)(s: String) = f(s) + val ans = jf1(fnd1)(str) + assertEquals(ans, sf1(sfnd)(str), 1e-9) + assertEquals(ans, jf1(sfnd.asJava)(str), 1e-9) + assertEquals(ans, sf1(fnd1.asScala)(str), 1e-9) + assertEquals(ans, jf1(asJavaToDoubleFunction(sfnd))(str), 1e-9) + assertEquals(ans, sf1(asScalaFromToDoubleFunction(fnd1))(str), 1e-9) + } + { + val fnd2 = new ToDoubleFunction[Double]{ def applyAsDouble(d: Double) = 1.0 - d } + val zfnd = (d: Double) => 1.0 - d + def jf2(tdf: ToDoubleFunction[Double])(x: Double) = tdf.applyAsDouble(x) + def sf2(f: Double => Double)(x: Double) = f(x) + val ans = jf2(fnd2)(nnn) + assertEquals(ans, sf2(zfnd)(nnn), 1e-9) + // assertEquals(ans, jf2(znfd.asJava)(nnn), 1e-9) -- DoubleUnaryOperator + assertEquals(ans, sf2(asScalaFromToDoubleFunction(fnd2))(nnn), 1e-9) + assertEquals(ans, jf2(asJavaToDoubleFunction(zfnd))(nnn), 1e-9) + } + } + + // ToIntBiFunction tests; conceptually widens to BiFunction and narrows to IntBinaryOperator + @Test + def test_ToIntBiFunction { + { + val bfi1 = new ToIntBiFunction[String, File]{ def applyAsInt(s: String, f: File) = s.length + f.getName.length } + val sbfi = (s: String, f: File) => s.length.toInt + f.getName.length + def jf1(tdbf: ToIntBiFunction[String, File])(s: String, f: File) = tdbf.applyAsInt(s,f) + def sf1(f: (String, File) => Int)(s: String, fi: File) = f(s,fi) + val ans = jf1(bfi1)(str, fyl) + assertEquals(ans, sf1(sbfi)(str, fyl)) + assertEquals(ans, jf1(sbfi.asJava)(str, fyl)) + assertEquals(ans, sf1(bfi1.asScala)(str, fyl)) + assertEquals(ans, jf1(asJavaToIntBiFunction(sbfi))(str, fyl)) + assertEquals(ans, sf1(asScalaFromToIntBiFunction(bfi1))(str, fyl)) + } + { + val bfi2 = new ToIntBiFunction[Int, File]{ def applyAsInt(i: Int, f: File) = i * f.getName.length } + val zbfi = (a: Int, f: File) => a * f.getName.length + def jf2(tdbf: ToIntBiFunction[Int, File])(a: Int, f: File) = tdbf.applyAsInt(a,f) + def sf2(f: (Int, File) => Int)(a: Int, fi: File) = f(a,fi) + val ans = jf2(bfi2)(num, fyl) + assertEquals(ans, sf2(zbfi)(num, fyl)) + assertEquals(ans, jf2(zbfi.asJava)(num, fyl)) + assertEquals(ans, sf2(bfi2.asScala)(num, fyl)) + assertEquals(ans, jf2(asJavaToIntBiFunction(zbfi))(num, fyl)) + assertEquals(ans, sf2(asScalaFromToIntBiFunction(bfi2))(num, fyl)) + } + } + + // ToIntFunction tests; conceptually widens to Function and narrows to IntUnaryOperator, etc.. + @Test + def test_ToIntFunction { + { + val fni1 = new ToIntFunction[String]{ def applyAsInt(s: String) = s.length } + val sfni = (s: String) => s.length + def jf1(tdf: ToIntFunction[String])(s: String) = tdf.applyAsInt(s) + def sf1(f: String => Int)(s: String) = f(s) + val ans = jf1(fni1)(str) + assertEquals(ans, sf1(sfni)(str)) + assertEquals(ans, jf1(sfni.asJava)(str)) + assertEquals(ans, sf1(fni1.asScala)(str)) + assertEquals(ans, jf1(asJavaToIntFunction(sfni))(str)) + assertEquals(ans, sf1(asScalaFromToIntFunction(fni1))(str)) + } + { + val fni2 = new ToIntFunction[Int]{ def applyAsInt(i: Int) = -i } + val zfni = (x: Int) => -x + def jf2(tdf: ToIntFunction[Int])(x: Int) = tdf.applyAsInt(x) + def sf2(f: Int => Int)(x: Int) = f(x) + val ans = jf2(fni2)(num) + assertEquals(ans, sf2(zfni)(num)) + // assertEquals(ans, jf2(znfd.asJava)(num)) -- IntUnaryOperator + assertEquals(ans, sf2(asScalaFromToIntFunction(fni2))(num)) + assertEquals(ans, jf2(asJavaToIntFunction(zfni))(num)) + } + } + + // ToLongBiFunction tests; conceptually widens to BiFunction and narrows to LongBinaryOperator + @Test + def test_ToLongBiFunction{ + { + val bfl1 = new ToLongBiFunction[String, File]{ def applyAsLong(s: String, f: File) = s.length * f.getName.length } + val sbfl = (s: String, f: File) => s.length.toLong * f.getName.length + def jf1(tdbf: ToLongBiFunction[String, File])(s: String, f: File) = tdbf.applyAsLong(s,f) + def sf1(f: (String, File) => Long)(s: String, fi: File) = f(s,fi) + val ans = jf1(bfl1)(str, fyl) + assertEquals(ans, sf1(sbfl)(str, fyl)) + assertEquals(ans, jf1(sbfl.asJava)(str, fyl)) + assertEquals(ans, sf1(bfl1.asScala)(str, fyl)) + assertEquals(ans, jf1(asJavaToLongBiFunction(sbfl))(str, fyl)) + assertEquals(ans, sf1(asScalaFromToLongBiFunction(bfl1))(str, fyl)) + } + { + val bfl2 = new ToLongBiFunction[Long, File]{ def applyAsLong(l: Long, f: File) = l ^ f.getName.length } + val zbfl = (a: Long, f: File) => a ^ f.getName.length + def jf2(tdbf: ToLongBiFunction[Long, File])(a: Long, f: File) = tdbf.applyAsLong(a,f) + def sf2(f: (Long, File) => Long)(a: Long, fi: File) = f(a,fi) + val ans = jf2(bfl2)(nmm, fyl) + assertEquals(ans, sf2(zbfl)(nmm, fyl)) + assertEquals(ans, jf2(zbfl.asJava)(nmm, fyl)) + assertEquals(ans, sf2(bfl2.asScala)(nmm, fyl)) + assertEquals(ans, jf2(asJavaToLongBiFunction(zbfl))(nmm, fyl)) + assertEquals(ans, sf2(asScalaFromToLongBiFunction(bfl2))(nmm, fyl)) + } + } + + // ToLongFunction tests; conceptually widens to Function and narrows to LongUnaryOperator, LongToIntFunction etc.. + @Test + def test_ToLongFunction { + { + val fnl1 = new ToLongFunction[String]{ def applyAsLong(s: String) = s.length.toLong << 16 } + val sfnl = (s: String) => s.length.toLong << 16 + def jf1(tdf: ToLongFunction[String])(s: String) = tdf.applyAsLong(s) + def sf1(f: String => Long)(s: String) = f(s) + val ans = jf1(fnl1)(str) + assertEquals(ans, sf1(sfnl)(str)) + assertEquals(ans, jf1(sfnl.asJava)(str)) + assertEquals(ans, sf1(fnl1.asScala)(str)) + assertEquals(ans, jf1(asJavaToLongFunction(sfnl))(str)) + assertEquals(ans, sf1(asScalaFromToLongFunction(fnl1))(str)) + } + { + val fnl2 = new ToLongFunction[Long]{ def applyAsLong(l: Long) = 2 - l } + val zfnl = (x: Long) => 2 - x + def jf2(tdf: ToLongFunction[Long])(x: Long) = tdf.applyAsLong(x) + def sf2(f: Long => Long)(x: Long) = f(x) + val ans = jf2(fnl2)(num) + assertEquals(ans, sf2(zfnl)(num)) + // assertEquals(ans, jf2(znfd.asJava)(num)) -- LongUnaryOperator + assertEquals(ans, sf2(asScalaFromToLongFunction(fnl2))(num)) + assertEquals(ans, jf2(asJavaToLongFunction(zfnl))(num)) + } + } + + // UnaryOperator tests; actually widens to Function and conceptually narrows to IntUnaryOperator etc.. + @Test + def test_UnaryOperator { + { + val uop1 = new UnaryOperator[String]{ def apply(s: String) = s.toUpperCase } + val suop = (s: String) => s.toUpperCase + def foo(uo: UnaryOperator[String])(s: String) = uo(s) + def bar(f: String => String)(s: String) = foo(f.asJava)(s) + def baz(uo: UnaryOperator[String])(s: String) = bar(uo.asScala)(s) + assertEquals(foo(uop1)(str), bar(suop)(str)) + assertEquals(foo(uop1)(str), baz(uop1)(str)) + assertEquals(foo(uop1)(str), bar(asScalaFromUnaryOperator(uop1))(str)) + assertEquals(foo(uop1)(str), baz(asJavaUnaryOperator(suop))(str)) + } + { + val uop2 = new UnaryOperator[Int]{ def apply(i: Int) = -i } + def zuop = (i: Int) => -i + def foo(uo: UnaryOperator[Int])(i: Int) = uo(i) + def bar(f: Int => Int)(i: Int) = foo(asJavaUnaryOperator(f))(i) // .asScala gives IntUnaryOperator + def baz(uo: UnaryOperator[Int])(i: Int) = bar(uo.asScala)(i) + assertEquals(foo(uop2)(num), bar(zuop)(num)) + assertEquals(foo(uop2)(num), baz(uop2)(num)) + assertEquals(foo(uop2)(num), bar(asScalaFromUnaryOperator(uop2))(num)) + } + } +} From 1682da0bcdbbb8a2c0666c7860c380ba7faf53d9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 28 Jul 2015 21:00:09 +1000 Subject: [PATCH 013/340] Reformat java sources to four space indent. And optimize imports. --- .../compat/java8/FutureConvertersTest.java | 578 +++++++++--------- 1 file changed, 288 insertions(+), 290 deletions(-) diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index d7fc1f2..a8d4861 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -3,321 +3,319 @@ */ package scala.compat.java8; +import org.junit.Test; +import scala.concurrent.Future; +import scala.concurrent.Promise; + import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; -import static java.util.concurrent.TimeUnit.*; +import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.*; - -import org.junit.Test; - -import scala.concurrent.Future; -import scala.concurrent.Promise; import static scala.compat.java8.FutureConverters.*; public class FutureConvertersTest { - @Test - public void testToScalaSuccess() { - final CompletableFuture cs = new CompletableFuture<>(); - final Future f = toScala(cs); - assertFalse("f must not yet be completed", f.isCompleted()); - cs.complete("Hello"); - assertTrue("f must be completed by now", f.isCompleted()); - assertEquals("Hello", f.value().get().get()); - } - - @Test - public void testToScalaFailure() { - final CompletableFuture cs = new CompletableFuture<>(); - final Future f = toScala(cs); - assertFalse("f must not yet be completed", f.isCompleted()); - final Exception ex = new RuntimeException("Hello"); - cs.completeExceptionally(ex); - assertTrue("f must be completed by now", f.isCompleted()); - assertEquals(ex, f.value().get().failed().get()); - } + @Test + public void testToScalaSuccess() { + final CompletableFuture cs = new CompletableFuture<>(); + final Future f = toScala(cs); + assertFalse("f must not yet be completed", f.isCompleted()); + cs.complete("Hello"); + assertTrue("f must be completed by now", f.isCompleted()); + assertEquals("Hello", f.value().get().get()); + } - @Test - public void testToJavaSuccess() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletableFuture cp = (CompletableFuture) cs; - assertFalse("cs must not yet be completed", cp.isDone()); - p.success("Hello"); - assertTrue("cs must be completed by now", cp.isDone()); - assertEquals("Hello", cp.get()); - } + @Test + public void testToScalaFailure() { + final CompletableFuture cs = new CompletableFuture<>(); + final Future f = toScala(cs); + assertFalse("f must not yet be completed", f.isCompleted()); + final Exception ex = new RuntimeException("Hello"); + cs.completeExceptionally(ex); + assertTrue("f must be completed by now", f.isCompleted()); + assertEquals(ex, f.value().get().failed().get()); + } - @Test - public void testToJavaFailure() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletableFuture cp = (CompletableFuture) cs; - assertFalse("cs must not yet be completed", cp.isDone()); - final Exception ex = new RuntimeException("Hello"); - p.failure(ex); - assertTrue("cs must be completed by now", cp.isDone()); - assertEquals("exceptionally equals", ex.toString(), cp.exceptionally(x -> x.toString()).get()); - Throwable thr = null; - try { - cp.get(); - } catch (Throwable t) { - thr = t; + @Test + public void testToJavaSuccess() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletableFuture cp = (CompletableFuture) cs; + assertFalse("cs must not yet be completed", cp.isDone()); + p.success("Hello"); + assertTrue("cs must be completed by now", cp.isDone()); + assertEquals("Hello", cp.get()); } - assertNotNull("get() must throw", thr); - assertEquals("thrown exception must be wrapped", ExecutionException.class, thr.getClass()); - assertEquals("wrapper must contain the right exception", ex, thr.getCause()); - } - @Test - public void testToJavaThenApply() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenApply(x -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return x; - }); - p.success("Hello"); - latch.countDown(); - assertEquals("Hello", second.toCompletableFuture().get()); - } + @Test + public void testToJavaFailure() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletableFuture cp = (CompletableFuture) cs; + assertFalse("cs must not yet be completed", cp.isDone()); + final Exception ex = new RuntimeException("Hello"); + p.failure(ex); + assertTrue("cs must be completed by now", cp.isDone()); + assertEquals("exceptionally equals", ex.toString(), cp.exceptionally(x -> x.toString()).get()); + Throwable thr = null; + try { + cp.get(); + } catch (Throwable t) { + thr = t; + } + assertNotNull("get() must throw", thr); + assertEquals("thrown exception must be wrapped", ExecutionException.class, thr.getClass()); + assertEquals("wrapper must contain the right exception", ex, thr.getCause()); + } - @Test - public void testToJavaThenAccept() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenAccept(x -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenApply() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenApply(x -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return x; + }); + p.success("Hello"); + latch.countDown(); + assertEquals("Hello", second.toCompletableFuture().get()); + } - @Test - public void testToJavaThenRun() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenRun(() -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenAccept() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenAccept(x -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaThenCombine() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = CompletableFuture.completedFuture(42); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenCombine(other, (x, y) -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return x.length() + y; - }); - p.success("Hello"); - latch.countDown(); - assertEquals((Integer) 47, second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenRun() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenRun(() -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaThenAcceptBoth() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = CompletableFuture.completedFuture(42); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenAcceptBoth(other, (x, y) -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenCombine() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = CompletableFuture.completedFuture(42); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenCombine(other, (x, y) -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return x.length() + y; + }); + p.success("Hello"); + latch.countDown(); + assertEquals((Integer) 47, second.toCompletableFuture().get()); + } - @Test - public void testToJavaRunAfterBoth() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = CompletableFuture.completedFuture(42); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.runAfterBoth(other, () -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenAcceptBoth() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = CompletableFuture.completedFuture(42); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenAcceptBoth(other, (x, y) -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaApplyToEither() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = new CompletableFuture<>(); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.applyToEither(other, x -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return x.length(); - }); - p.success("Hello"); - latch.countDown(); - assertEquals((Integer) 5, second.toCompletableFuture().get()); - } + @Test + public void testToJavaRunAfterBoth() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = CompletableFuture.completedFuture(42); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.runAfterBoth(other, () -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaAcceptEither() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = new CompletableFuture<>(); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.acceptEither(other, x -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaApplyToEither() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = new CompletableFuture<>(); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.applyToEither(other, x -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return x.length(); + }); + p.success("Hello"); + latch.countDown(); + assertEquals((Integer) 5, second.toCompletableFuture().get()); + } - @Test - public void testToJavaRunAfterEither() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CompletionStage other = new CompletableFuture<>(); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.runAfterEither(other, () -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - p.success("Hello"); - latch.countDown(); - assertNull("result must be Void", second.toCompletableFuture().get()); - } + @Test + public void testToJavaAcceptEither() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = new CompletableFuture<>(); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.acceptEither(other, x -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaThenCompose() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.thenCompose(x -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception e) { - throw new RuntimeException(e); - } - return CompletableFuture.completedFuture(x); - }); - p.success("Hello"); - latch.countDown(); - assertEquals("Hello", second.toCompletableFuture().get()); - } + @Test + public void testToJavaRunAfterEither() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CompletionStage other = new CompletableFuture<>(); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.runAfterEither(other, () -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + p.success("Hello"); + latch.countDown(); + assertNull("result must be Void", second.toCompletableFuture().get()); + } - @Test - public void testToJavaWhenComplete() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.whenComplete((v, e) -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - }); - p.success("Hello"); - latch.countDown(); - assertEquals("Hello", second.toCompletableFuture().get()); - } + @Test + public void testToJavaThenCompose() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.thenCompose(x -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception e) { + throw new RuntimeException(e); + } + return CompletableFuture.completedFuture(x); + }); + p.success("Hello"); + latch.countDown(); + assertEquals("Hello", second.toCompletableFuture().get()); + } - @Test - public void testToJavaHandle() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.handle((v, e) -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return v.length(); - }); - p.success("Hello"); - latch.countDown(); - assertEquals((Integer) 5, second.toCompletableFuture().get()); - } + @Test + public void testToJavaWhenComplete() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.whenComplete((v, e) -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + }); + p.success("Hello"); + latch.countDown(); + assertEquals("Hello", second.toCompletableFuture().get()); + } - @Test - public void testToJavaExceptionally() throws InterruptedException, - ExecutionException { - final Promise p = promise(); - final CompletionStage cs = toJava(p.future()); - final CountDownLatch latch = new CountDownLatch(1); - final CompletionStage second = cs.exceptionally(e -> { - try { - assertTrue("latch must succeed", latch.await(1, SECONDS)); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - return e.getMessage(); - }); - p.failure(new RuntimeException("Hello")); - latch.countDown(); - assertEquals("Hello", second.toCompletableFuture().get()); - } + @Test + public void testToJavaHandle() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.handle((v, e) -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + return v.length(); + }); + p.success("Hello"); + latch.countDown(); + assertEquals((Integer) 5, second.toCompletableFuture().get()); + } + @Test + public void testToJavaExceptionally() throws InterruptedException, + ExecutionException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + final CountDownLatch latch = new CountDownLatch(1); + final CompletionStage second = cs.exceptionally(e -> { + try { + assertTrue("latch must succeed", latch.await(1, SECONDS)); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + return e.getMessage(); + }); + p.failure(new RuntimeException("Hello")); + latch.countDown(); + assertEquals("Hello", second.toCompletableFuture().get()); + } } From 89475834d03af73f898e96545953ba7fe18530a7 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 5 Jun 2015 06:50:49 +0200 Subject: [PATCH 014/340] Add Scala 2.12.0-M2 as a cross build Avoid inheritance from DefaultPromise, which is final in 2.12. --- .travis.yml | 3 ++- build.sbt | 7 ++++--- .../scala/scala/compat/java8/FutureConverters.scala | 10 ++++++++-- .../scala/concurrent/java8/FutureConvertersImpl.scala | 7 ------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index aa3ffa3..c926215 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,8 @@ env: script: - admin/build.sh scala: - - 2.11.6 + - 2.11.7 + - 2.12.0-M2 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index fa1d549..d959560 100644 --- a/build.sbt +++ b/build.sbt @@ -9,7 +9,8 @@ def jwrite(dir: java.io.File)(name: String, content: String) = { } lazy val commonSettings = Seq( - scalaVersion := "2.11.6", + scalaVersion := "2.11.7", + crossScalaVersions := List("2.11.7", "2.12.0-M2"), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, @@ -100,8 +101,8 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.8" cross CrossVersion.full), - scalacOptions in Compile <+= target map (t => "-P:genjavadoc:out=" + (t / "java")) + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.9" cross CrossVersion.full), + scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). settings( diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 86fdddf..a2c0977 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -71,8 +71,14 @@ object FutureConverters { * @return a Scala Future that represents the CompletionStage's completion */ def toScala[T](cs: CompletionStage[T]): Future[T] = { - val p = new P[T] - cs whenComplete p + val p = Promise[T]() + val bc = new BiConsumer[T, Throwable] { + override def accept(v: T, e: Throwable): Unit = { + if (e == null) p.complete(Success(v)) + else p.complete(Failure(e)) + } + } + cs whenComplete bc p.future } diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 14a917f..5c907e7 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -71,11 +71,4 @@ object FuturesConvertersImpl { override def toString: String = super[CompletableFuture].toString } - - class P[T] extends impl.Promise.DefaultPromise[T] with BiConsumer[T, Throwable] { - override def accept(v: T, e: Throwable): Unit = { - if (e == null) complete(Success(v)) - else complete(Failure(e)) - } - } } From 7bc38cb0a8a5261fd34414fc5d6fc01d19fa6d3d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 28 Jul 2015 21:09:39 +1000 Subject: [PATCH 015/340] Support blocking with: `scalaFuture.toJava.toCompletableFuture` I believe this implements the somewhat reluctant consensus reached in #43. Go with the flow by allowing people to block using the standard Java 8 idiom of `toCompletableFuture.get`. I've added a comment and a test to caution that calling `toCompletableFuture.complete(value)` does *not* effect the underlying Promise. Fixes #43 --- .../java8/FutureConvertersImpl.scala | 11 +++++++-- .../compat/java8/FutureConvertersTest.java | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 5c907e7..48c861c 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -66,8 +66,15 @@ object FuturesConvertersImpl { cf } - override def toCompletableFuture(): CompletableFuture[T] = - throw new UnsupportedOperationException("this CompletionStage represents a read-only Scala Future") + /** + * @inheritdoc + * + * WARNING: completing the result of this method will not complete the underlying + * Scala Future or Promise. + */ + override def toCompletableFuture(): CompletableFuture[T] = { + this // TODO or maybe `thenApply(JF.identity())` + } override def toString: String = super[CompletableFuture].toString } diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index a8d4861..aaaccc0 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -318,4 +318,27 @@ public void testToJavaExceptionally() throws InterruptedException, latch.countDown(); assertEquals("Hello", second.toCompletableFuture().get()); } + + @Test + public void testToJavaToCompletableFuture() throws ExecutionException, InterruptedException { + final Promise p = promise(); + final CompletionStage cs = toJava(p.future()); + CompletableFuture cf = cs.toCompletableFuture(); + assertEquals("notyet", cf.getNow("notyet")); + p.success("done"); + assertEquals("done", cf.get()); + } + + @Test + public void testToJavaToCompletableFutureDoesNotMutateUnderlyingPromise() throws ExecutionException, InterruptedException { + final Promise p = promise(); + Future sf = p.future(); + final CompletionStage cs = toJava(sf); + CompletableFuture cf = cs.toCompletableFuture(); + assertEquals("notyet", cf.getNow("notyet")); + cf.complete("done"); + assertEquals("done", cf.get()); + assertFalse(sf.isCompleted()); + assertFalse(p.isCompleted()); + } } From 46d8b308701271c606830cd859dbe72370810568 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 28 Jul 2015 22:10:42 +1000 Subject: [PATCH 016/340] Test case for toJava / thenCompose that now works Since `toCompletableFuture` stopped throwing an `UnsupportedOperationException` in the previous commit, this use case is now supported. Fixes #29 --- .../compat/java8/FutureConvertersTest.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index aaaccc0..81b0d5f 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -7,11 +7,9 @@ import scala.concurrent.Future; import scala.concurrent.Promise; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.*; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.*; import static scala.compat.java8.FutureConverters.*; @@ -319,6 +317,30 @@ public void testToJavaExceptionally() throws InterruptedException, assertEquals("Hello", second.toCompletableFuture().get()); } + @Test + public void testToJavaThenComposeWithToJavaThenAccept() throws InterruptedException, + ExecutionException, TimeoutException { + final Promise p1 = promise(); + final CompletableFuture future = new CompletableFuture<>(); + + final CompletionStage second = + CompletableFuture.supplyAsync(() -> "Hello"). + thenCompose(x -> toJava(p1.future())); + + second.handle((x, t) -> { + if (t != null) { + t.printStackTrace(); + future.completeExceptionally(t); + } else { + future.complete(x); + } + return null; + }); + + p1.success("Hello"); + assertEquals("Hello", future.get(1000, MILLISECONDS)); + } + @Test public void testToJavaToCompletableFuture() throws ExecutionException, InterruptedException { final Promise p = promise(); From 9cb51e64e061de57a88f34a69ac409fe21a8af20 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 29 Jul 2015 10:33:49 +1000 Subject: [PATCH 017/340] Extra test and comment suggested during review --- .../concurrent/java8/FutureConvertersImpl.scala | 2 +- .../scala/compat/java8/FutureConvertersTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 48c861c..c7d29b0 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -70,7 +70,7 @@ object FuturesConvertersImpl { * @inheritdoc * * WARNING: completing the result of this method will not complete the underlying - * Scala Future or Promise. + * Scala Future or Promise (ie, the one that that was passed to `toJava`.) */ override def toCompletableFuture(): CompletableFuture[T] = { this // TODO or maybe `thenApply(JF.identity())` diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index 81b0d5f..a06fc3c 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -363,4 +363,17 @@ public void testToJavaToCompletableFutureDoesNotMutateUnderlyingPromise() throws assertFalse(sf.isCompleted()); assertFalse(p.isCompleted()); } + + @Test + public void testToJavaToCompletableFutureJavaCompleteCallledAfterScalaComplete() throws ExecutionException, InterruptedException { + final Promise p = promise(); + Future sf = p.future(); + final CompletionStage cs = toJava(sf); + CompletableFuture cf = cs.toCompletableFuture(); + assertEquals("notyet", cf.getNow("notyet")); + p.success("scaladone"); + assertEquals("scaladone", cf.get()); + cf.complete("javadone"); + assertEquals("scaladone", cf.get()); + } } From 976605e7134cbd079af297a171277f14eec9f3b0 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 13 Aug 2015 15:39:05 +1000 Subject: [PATCH 018/340] Simplify and not the source of a test case --- .../compat/java8/FutureConvertersTest.java | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index a06fc3c..4f0421f 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -320,23 +320,12 @@ public void testToJavaExceptionally() throws InterruptedException, @Test public void testToJavaThenComposeWithToJavaThenAccept() throws InterruptedException, ExecutionException, TimeoutException { + // Test case from https://github.com/scala/scala-java8-compat/issues/29 final Promise p1 = promise(); final CompletableFuture future = new CompletableFuture<>(); - final CompletionStage second = - CompletableFuture.supplyAsync(() -> "Hello"). - thenCompose(x -> toJava(p1.future())); - - second.handle((x, t) -> { - if (t != null) { - t.printStackTrace(); - future.completeExceptionally(t); - } else { - future.complete(x); - } - return null; - }); - + CompletableFuture.supplyAsync(() -> "Hello"). + thenCompose(x -> toJava(p1.future())).handle((x, t) -> future.complete(x)); p1.success("Hello"); assertEquals("Hello", future.get(1000, MILLISECONDS)); } From 4b85f72c433ef9b6a1c94d60ad474c9e5223205b Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 13 Aug 2015 15:42:18 +1000 Subject: [PATCH 019/340] Test case to show completion from Java future before Scala future --- .../scala/compat/java8/FutureConvertersTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index 4f0421f..12fc108 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -354,7 +354,7 @@ public void testToJavaToCompletableFutureDoesNotMutateUnderlyingPromise() throws } @Test - public void testToJavaToCompletableFutureJavaCompleteCallledAfterScalaComplete() throws ExecutionException, InterruptedException { + public void testToJavaToCompletableFutureJavaCompleteCalledAfterScalaComplete() throws ExecutionException, InterruptedException { final Promise p = promise(); Future sf = p.future(); final CompletionStage cs = toJava(sf); @@ -365,4 +365,17 @@ public void testToJavaToCompletableFutureJavaCompleteCallledAfterScalaComplete() cf.complete("javadone"); assertEquals("scaladone", cf.get()); } + + @Test + public void testToJavaToCompletableFutureJavaCompleteCalledBeforeScalaComplete() throws ExecutionException, InterruptedException { + final Promise p = promise(); + Future sf = p.future(); + final CompletionStage cs = toJava(sf); + CompletableFuture cf = cs.toCompletableFuture(); + assertEquals("notyet", cf.getNow("notyet")); + cf.complete("javadone"); + assertEquals("javadone", cf.get()); + p.success("scaladone"); + assertEquals("javadone", cf.get()); + } } From fcdda1a91479d78a49c9b4921b531a788b407b38 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 13 Aug 2015 20:32:12 +1000 Subject: [PATCH 020/340] Remove vague TODO comment. I wasn't sure which way to go here, but now we have a few more tests I guess this comment doesn't really help anyone. --- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index c7d29b0..fff1986 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -73,7 +73,7 @@ object FuturesConvertersImpl { * Scala Future or Promise (ie, the one that that was passed to `toJava`.) */ override def toCompletableFuture(): CompletableFuture[T] = { - this // TODO or maybe `thenApply(JF.identity())` + this } override def toString: String = super[CompletableFuture].toString From 385de85dbfbff40c630ef6dcf6c39438db21839d Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 13 Aug 2015 20:42:22 +1000 Subject: [PATCH 021/340] Use `s.c.blocking` in `future.toJava.get` As suggested by Viktor. --- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index fff1986..7e77fa4 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -6,7 +6,7 @@ package scala.concurrent.java8 // Located in this package to access private[concurrent] members import scala.concurrent.{ Future, Promise, ExecutionContext, ExecutionContextExecutorService, ExecutionContextExecutor, impl } -import java.util.concurrent.{ CompletionStage, Executor, ExecutorService, CompletableFuture } +import java.util.concurrent._ import scala.util.{ Try, Success, Failure } import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } @@ -76,6 +76,10 @@ object FuturesConvertersImpl { this } + override def get(): T = scala.concurrent.blocking(super.get()) + + override def get(timeout: Long, unit: TimeUnit): T = scala.concurrent.blocking(super.get(timeout, unit)) + override def toString: String = super[CompletableFuture].toString } } From 1d60cd0aca03c9721c0d597c7251db963a967d74 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 17 Aug 2015 14:54:15 +1000 Subject: [PATCH 022/340] Make toJava(scalaFuture).toCF.obtrude* unsupported The status quo was to allow the wrapper and the wrapped to diverge; the as shown by: ``` @Test public void testToJavaToCompletableFutureJavaObtrudeCalledAfterScalaComplete() throws Exception { final Promise p = promise(); Future sf = p.future(); final CompletionStage cs = toJava(sf); CompletableFuture cf = cs.toCompletableFuture(); assertEquals("notyet", cf.getNow("notyet")); p.success("scaladone"); assertEquals("scaladone", cf.get()); cf.obtrudeValue("javadone"); assertEquals("javadone", cf.get()); // obtrude does not mutate the underlying Scala future assertEquals("scaladone", Await.result(sf, Duration.Inf())); } ``` This commit throws an UOE, preferring to fail fast. --- .../java8/FutureConvertersImpl.scala | 8 +++++--- .../compat/java8/FutureConvertersTest.java | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 7e77fa4..1ee934e 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -72,9 +72,11 @@ object FuturesConvertersImpl { * WARNING: completing the result of this method will not complete the underlying * Scala Future or Promise (ie, the one that that was passed to `toJava`.) */ - override def toCompletableFuture(): CompletableFuture[T] = { - this - } + override def toCompletableFuture(): CompletableFuture[T] = this + + override def obtrudeValue(value: T): Unit = throw new UnsupportedOperationException("obtrudeValue may not be used on the result of toJava(scalaFuture)") + + override def obtrudeException(ex: Throwable): Unit = throw new UnsupportedOperationException("obtrudeException may not be used on the result of toJava(scalaFuture)") override def get(): T = scala.concurrent.blocking(super.get()) diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index 12fc108..7735aba 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -378,4 +378,24 @@ public void testToJavaToCompletableFutureJavaCompleteCalledBeforeScalaComplete() p.success("scaladone"); assertEquals("javadone", cf.get()); } + + @Test + public void testToJavaToCompletableFutureJavaObtrudeCalledBeforeScalaComplete() throws ExecutionException, InterruptedException { + final Promise p = promise(); + Future sf = p.future(); + final CompletionStage cs = toJava(sf); + CompletableFuture cf = cs.toCompletableFuture(); + try { + cf.obtrudeValue(""); + fail(); + } catch (UnsupportedOperationException iae) { + // okay + } + try { + cf.obtrudeException(new Exception()); + fail(); + } catch (UnsupportedOperationException iae) { + // okay + } + } } From 9eb940da8484181be3cb1a737eb746b0a9444628 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 28 Jul 2015 21:59:44 +1000 Subject: [PATCH 023/340] More efficient round trip conversions for Futures Makes `toJava.toScala` and `toScala.toJava` a wrap-and-unwrap operation, rather than a wrap-and-rewrap. Removes the cross build on 2.12, we should wait until 2.12.0-M3 in which DefaultPromise is once again extendable. See: https://github.com/retronym/scala-java8-compat/commit/4faeac5 https://github.com/scala/scala/pull/4690 --- .travis.yml | 2 +- build.sbt | 2 +- .../scala/compat/java8/FutureConverters.scala | 26 ++++++++++--------- .../java8/FutureConvertersImpl.scala | 14 ++++++++-- .../compat/java8/FutureConvertersTest.java | 19 ++++++++++++++ 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index c926215..dc8415a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - admin/build.sh scala: - 2.11.7 - - 2.12.0-M2 + # - 2.12.0-M3 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index d959560..1b105c7 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ def jwrite(dir: java.io.File)(name: String, content: String) = { lazy val commonSettings = Seq( scalaVersion := "2.11.7", - crossScalaVersions := List("2.11.7", "2.12.0-M2"), + crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index a2c0977..c065e49 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -54,10 +54,14 @@ object FutureConverters { * not support the CompletableFuture interface */ def toJava[T](f: Future[T]): CompletionStage[T] = { - val cf = new CF[T] - implicit val ec = InternalCallbackExecutor - f onComplete cf - cf + f match { + case p: P[T] => p.wrapped + case _ => + val cf = new CF[T](f) + implicit val ec = InternalCallbackExecutor + f onComplete cf + cf + } } /** @@ -71,15 +75,13 @@ object FutureConverters { * @return a Scala Future that represents the CompletionStage's completion */ def toScala[T](cs: CompletionStage[T]): Future[T] = { - val p = Promise[T]() - val bc = new BiConsumer[T, Throwable] { - override def accept(v: T, e: Throwable): Unit = { - if (e == null) p.complete(Success(v)) - else p.complete(Failure(e)) - } + cs match { + case cf: CF[T] => cf.wrapped + case _ => + val p = new P[T](cs) + cs whenComplete p + p.future } - cs whenComplete bc - p.future } /** diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 1ee934e..edc8723 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -5,8 +5,9 @@ package scala.concurrent.java8 // Located in this package to access private[concurrent] members -import scala.concurrent.{ Future, Promise, ExecutionContext, ExecutionContextExecutorService, ExecutionContextExecutor, impl } +import scala.concurrent.{ Future, ExecutionContext } import java.util.concurrent._ +import scala.concurrent.impl.Promise.DefaultPromise import scala.util.{ Try, Success, Failure } import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } @@ -14,7 +15,7 @@ import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } object FuturesConvertersImpl { def InternalCallbackExecutor = Future.InternalCallbackExecutor - class CF[T] extends CompletableFuture[T] with (Try[T] => Unit) { + class CF[T](val wrapped: Future[T]) extends CompletableFuture[T] with (Try[T] => Unit) { override def apply(t: Try[T]): Unit = t match { case Success(v) ⇒ complete(v) case Failure(e) ⇒ completeExceptionally(e) @@ -84,4 +85,13 @@ object FuturesConvertersImpl { override def toString: String = super[CompletableFuture].toString } + + class P[T](val wrapped: CompletionStage[T]) extends DefaultPromise[T] with BiConsumer[T, Throwable] { + override def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = super.onSuccess(pf) + + override def accept(v: T, e: Throwable): Unit = { + if (e == null) complete(Success(v)) + else complete(Failure(e)) + } + } } diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index 7735aba..a87a6b8 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -12,6 +12,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.junit.Assert.*; +import static org.junit.Assert.assertSame; import static scala.compat.java8.FutureConverters.*; public class FutureConvertersTest { @@ -398,4 +399,22 @@ public void testToJavaToCompletableFutureJavaObtrudeCalledBeforeScalaComplete() // okay } } + + @Test + public void testToJavaAndBackAvoidsWrappers() { + final Promise p = promise(); + final Future sf = p.future(); + final CompletionStage cs = toJava(sf); + Future sf1 = toScala(cs); + assertSame(sf, sf1); + } + + @Test + public void testToScalaAndBackAvoidsWrappers() { + final CompletableFuture cf = new CompletableFuture<>(); + final Future f = toScala(cf); + CompletionStage cs1 = toJava(f); + assertSame(cf, cs1); + + } } From d52904db4df1654cd6e48dfd797c4cb6acc235c2 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 28 Aug 2015 16:07:41 +1000 Subject: [PATCH 024/340] Add TravisCI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68dcc92..04b236d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) +## scala-java8-compat [](https://travis-ci.org/scala/async) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) A Java 8 compatibility kit for Scala. From 4313c267ac9bcfa72b34c27bcc24134fefc67c9a Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 28 Aug 2015 16:08:32 +1000 Subject: [PATCH 025/340] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04b236d..b3f11ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/async) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) +## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) A Java 8 compatibility kit for Scala. From 0722b7c31d0bcc86953738d98de65b1fbbabc6b9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 29 Aug 2015 21:21:55 +1000 Subject: [PATCH 026/340] Avoid unnecessary dependency on scala-{compiler,reflect}.jar These are only needed for the code generator sub project. Fixes #53 --- build.sbt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 1b105c7..957b394 100644 --- a/build.sbt +++ b/build.sbt @@ -12,15 +12,15 @@ lazy val commonSettings = Seq( scalaVersion := "2.11.7", crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), organization := "org.scala-lang.modules", - version := "0.6.0-SNAPSHOT", - libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, - libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value + version := "0.6.0-SNAPSHOT" ) lazy val fnGen = (project in file("fnGen")). settings(commonSettings: _*). settings( - fork in run := true // Needed if you run this project directly + fork in run := true, // Needed if you run this project directly + libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, + libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value ) lazy val root = (project in file(".")). From 6ff53ed8ad2deae551ef884efdd5bc60fcba92bc Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sat, 29 Aug 2015 21:56:30 +1000 Subject: [PATCH 027/340] Remove unneeded dependency core -> fnGen After this change: ``` org.scala-lang scala-library 2.11.7 junit junit 4.11 test org.apache.commons commons-lang3 3.4 test com.novocode junit-interface 0.10 test ``` Fixes #52 --- build.sbt | 1 - 1 file changed, 1 deletion(-) diff --git a/build.sbt b/build.sbt index 957b394..7209f4c 100644 --- a/build.sbt +++ b/build.sbt @@ -24,7 +24,6 @@ lazy val fnGen = (project in file("fnGen")). ) lazy val root = (project in file(".")). - dependsOn(fnGen). settings(scalaModuleSettings: _*). settings(commonSettings: _*). settings( From 15195784fab701140088cc8e510e20f508e78ea9 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 22 Dec 2015 13:28:07 +1100 Subject: [PATCH 028/340] Enable cross build for 2.12.0-M3 --- .travis.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index dc8415a..a7d0599 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - admin/build.sh scala: - 2.11.7 - # - 2.12.0-M3 + - 2.12.0-M3 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index 7209f4c..9c0d927 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ def jwrite(dir: java.io.File)(name: String, content: String) = { lazy val commonSettings = Seq( scalaVersion := "2.11.7", - crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), + crossScalaVersions := List("2.11.7", "2.12.0-M3"), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT" ) From 1562feb4f4d8e1b982863159b52b89a630277a1a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 29 Apr 2015 20:58:59 -0700 Subject: [PATCH 029/340] Basic implementation of Stepper which covers functionality of both Iterator and Spliterator and primitive versions thereof. (Will still need four implementations of some things, but this should reduce it a lot.) Also added Steppers for arrays to check performance. (Very good so far.) Have some terminal operations to Stepper. Trying to avoid the Stepper/StepperLike pattern, but I doubt I'll manage. --- .../scala/compat/java8/StepConverters.scala | 193 ++++++++++++++++++ .../scala/scala/compat/java8/Stepper.scala | 71 +++++++ 2 files changed, 264 insertions(+) create mode 100644 src/main/scala/scala/compat/java8/StepConverters.scala create mode 100644 src/main/scala/scala/compat/java8/Stepper.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala new file mode 100644 index 0000000..58e58ec --- /dev/null +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -0,0 +1,193 @@ +package scala.compat.java8 + +import language.implicitConversions + +package converterImpls { + import StepConverters.SplitFlags._ + + private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) + extends StepperGeneric[A] { + def semiclone(half: Int): STA + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): StepperGeneric[A] = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayGenObject[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) + extends StepperArrayAny[A, Array[A], StepperArrayGenObject[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenObject[A](underlying, i0, half) + } + + private[java8] class StepperArrayGenAny[A](underlying: Array[A], _i0: Int, _iN: Int) + extends StepperArrayAny[A, Array[A], StepperArrayGenAny[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenAny[A](underlying, i0, half) + } + + private[java8] class StepperArrayGenUnit(underlying: Array[Unit], _i0: Int, _iN: Int) + extends StepperArrayAny[Unit, Array[Unit], StepperArrayGenUnit](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenUnit(underlying, i0, half) + } + + private[java8] class StepperArrayGenBoolean(underlying: Array[Boolean], _i0: Int, _iN: Int) + extends StepperArrayAny[Boolean, Array[Boolean], StepperArrayGenBoolean](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenBoolean(underlying, i0, half) + } + + private[java8] class StepperArrayGenByte(underlying: Array[Byte], _i0: Int, _iN: Int) + extends StepperArrayAny[Byte, Array[Byte], StepperArrayGenByte](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenByte(underlying, i0, half) + } + + private[java8] class StepperArrayGenChar(underlying: Array[Char], _i0: Int, _iN: Int) + extends StepperArrayAny[Char, Array[Char], StepperArrayGenChar](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenChar(underlying, i0, half) + } + + private[java8] class StepperArrayGenShort(underlying: Array[Short], _i0: Int, _iN: Int) + extends StepperArrayAny[Short, Array[Short], StepperArrayGenShort](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenShort(underlying, i0, half) + } + + private[java8] class StepperArrayGenFloat(underlying: Array[Float], _i0: Int, _iN: Int) + extends StepperArrayAny[Float, Array[Float], StepperArrayGenFloat](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) + } + + private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends StepperDouble { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayDouble(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends StepperInt { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayInt(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends StepperLong { + def characteristics() = NonNull + Sized + Subsized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def substep() = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = new StepperArrayLong(underlying, i0, half) + i0 = half + ans + } + else null + } + } + + final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { + @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + } + + final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ + @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + } + + final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ + @inline def stepper: Stepper[Unit, StepperGeneric[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + } + + final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ + @inline def stepper: Stepper[Boolean, StepperGeneric[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + } + + final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ + @inline def stepper: Stepper[Byte, StepperGeneric[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + } + + final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ + @inline def stepper: Stepper[Char, StepperGeneric[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + } + + final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ + @inline def stepper: Stepper[Short, StepperGeneric[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + } + + final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ + @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + } + + trait Priority3StepConverters { + implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + } + + trait Priority2StepConverters extends Priority3StepConverters { + implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) + implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) + implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) + implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) + implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) + implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) + implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + } +} + +object StepConverters extends converterImpls.Priority2StepConverters { + object SplitFlags { + final val Concurrent = java.util.Spliterator.CONCURRENT + final val Distinct = java.util.Spliterator.DISTINCT + final val Immutable = java.util.Spliterator.IMMUTABLE + final val NonNull = java.util.Spliterator.NONNULL + final val HasOrder = java.util.Spliterator.ORDERED + final val Sized = java.util.Spliterator.SIZED + final val Sorted = java.util.Spliterator.SORTED + final val Subsized = java.util.Spliterator.SUBSIZED + } + import SplitFlags._ + import converterImpls._ + + implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { + def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + } + + implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { + def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + } + + implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { + def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + } +} diff --git a/src/main/scala/scala/compat/java8/Stepper.scala b/src/main/scala/scala/compat/java8/Stepper.scala new file mode 100644 index 0000000..22fdd5c --- /dev/null +++ b/src/main/scala/scala/compat/java8/Stepper.scala @@ -0,0 +1,71 @@ +package scala.compat.java8 + +trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { + def characteristics: Int + def hasStep: Boolean + def knownSize: Long + def nextStep: A + def tryStep(f: A => Unit): Boolean + def substep(): Stepper[A, CC] + def typedPrecisely: CC + + // Terminal operations that do not produce another Stepper + def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } + def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } + def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } + def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + def foreach(f: A => Unit) { while (hasStep) f(nextStep) } + def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } +} + +trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { + def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = next + def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false + def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: StepperGeneric[A] = this +} + +trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextDouble + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false + def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false + def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + +trait StepperInt extends Stepper[Int, StepperInt] with java.util.PrimitiveIterator.OfInt with java.util.Spliterator.OfInt { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextInt + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false + def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false + def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + +trait StepperLong extends Stepper[Long, StepperLong] with java.util.PrimitiveIterator.OfLong with java.util.Spliterator.OfLong { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextLong + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false + def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false + def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this +} + From f476c42bd61e155334f84f40a9789d702d4a81e1 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 1 May 2015 18:56:57 -0700 Subject: [PATCH 030/340] Further work on core stepper API. --- .../java8/Stepper.scala | 60 ++++++++++++++++++- .../scala/compat/java8/StepConverters.scala | 36 ++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) rename src/main/scala/scala/{compat => collection}/java8/Stepper.scala (68%) diff --git a/src/main/scala/scala/compat/java8/Stepper.scala b/src/main/scala/scala/collection/java8/Stepper.scala similarity index 68% rename from src/main/scala/scala/compat/java8/Stepper.scala rename to src/main/scala/scala/collection/java8/Stepper.scala index 22fdd5c..e433c9b 100644 --- a/src/main/scala/scala/compat/java8/Stepper.scala +++ b/src/main/scala/scala/collection/java8/Stepper.scala @@ -1,4 +1,4 @@ -package scala.compat.java8 +package scala.collection.java8 trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int @@ -6,18 +6,72 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def knownSize: Long def nextStep: A def tryStep(f: A => Unit): Boolean - def substep(): Stepper[A, CC] + def substep(): CC def typedPrecisely: CC - // Terminal operations that do not produce another Stepper + // Terminal operations (do not produce another Stepper) def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } +object Stepper { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { + private var cache: A = null.asInstanceOf[A] + private var cached: Boolean = false + def accept(a: A) { cache = a; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.Consumer[_ >: A]): Boolean = { + if (cached) { + c.accept(cache) + cache = null.asInstanceOf[A] + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def next = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cache = null.asInstanceOf[A] + cached = false + ans + } + def substep(): StepperGeneric[A] = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cache = null.asInstanceOf[A] + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) + } + def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) +} trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 58e58ec..ec5fd45 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -2,6 +2,8 @@ package scala.compat.java8 import language.implicitConversions +import scala.collection.java8._ + package converterImpls { import StepConverters.SplitFlags._ @@ -150,6 +152,30 @@ package converterImpls { @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends StepperInt { + def characteristics() = NonNull + def estimateSize = iN - i0 + def hasNext = i0 < iN + def nextInt() = { + if (hasNext()) { + val cp = underlying.codePointAt(i0) + i0 += java.lang.Character.charCount(cp) + cp + } + else throw new NoSuchElementException("Empty Stepper") + } + def substep() = { + if (iN-3 > i0) { + var half = (i0+iN) >>> 1 + if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 + val ans = new StepperStringCodePoint(underlying, i0, half) + i0 = half + ans + } + else null + } + } + trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) } @@ -180,14 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + } + + implicit class RichStringCanStep(val underlying: String) extends AnyVal { + @inline def stepper: Stepper[Int, StepperInt] = new StepperStringCodePoint(underlying, 0, underlying.length) } } From 1cf9ea2a904830f2aea341ec48dc0e9d1feaf578 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 23 Aug 2015 16:44:33 -0700 Subject: [PATCH 031/340] Basic conversion of Spliterator to Stepper works. --- .../compat/java8/SpliteratorConverters.scala | 29 ++++ .../scala/compat/java8/StepConverters.scala | 2 +- .../java8/collectionImpl}/Stepper.scala | 152 +++++++++++++++++- 3 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/SpliteratorConverters.scala rename src/main/scala/scala/{collection/java8 => compat/java8/collectionImpl}/Stepper.scala (56%) diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala new file mode 100644 index 0000000..a8bc6fb --- /dev/null +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -0,0 +1,29 @@ +package scala.compat.java8 + +import language.implicitConversions + +import java.util._ +import scala.compat.java8.collectionImpl._ + +package SpliteratorConverters { + class SpliteratorToStepper[A] private[java8] (private val underlying: Spliterator[A]) extends AnyVal { + def stepper: StepperGeneric[A] = Stepper.ofSpliterator(underlying) + } + + trait Priority2SpliteratorConverters { + implicit def spliteratorToStepper[A](sp: Spliterator[A]) = new SpliteratorToStepper[A](sp) + } +} + + +package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { + implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { + def stepper: StepperDouble = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { + def stepper: StepperInt = Stepper.ofSpliterator(underlying) + } + implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { + def stepper: StepperLong = Stepper.ofSpliterator(underlying) + } +} diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ec5fd45..ec95c35 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -2,7 +2,7 @@ package scala.compat.java8 import language.implicitConversions -import scala.collection.java8._ +import scala.compat.java8.collectionImpl._ package converterImpls { import StepConverters.SplitFlags._ diff --git a/src/main/scala/scala/collection/java8/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala similarity index 56% rename from src/main/scala/scala/collection/java8/Stepper.scala rename to src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index e433c9b..8c7eb5f 100644 --- a/src/main/scala/scala/collection/java8/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,4 +1,4 @@ -package scala.collection.java8 +package scala.compat.java8.collectionImpl trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int @@ -20,7 +20,8 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } object Stepper { - class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) + extends StepperGeneric[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] private var cached: Boolean = false def accept(a: A) { cache = a; cached = true } @@ -70,7 +71,154 @@ object Stepper { } override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } + class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) + extends StepperDouble with java.util.function.DoubleConsumer { + private var cache: Double = Double.NaN + private var cached: Boolean = false + def accept(d: Double) { cache = d; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.DoubleConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.DoubleConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextDouble = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperDouble = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfDoubleSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) + } + class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) + extends StepperInt with java.util.function.IntConsumer { + private var cache: Int = 0 + private var cached: Boolean = false + def accept(i: Int) { cache = i; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.IntConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.IntConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextInt = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperInt = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfIntSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) + } + class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) + extends StepperLong with java.util.function.LongConsumer { + private var cache: Long = 0L + private var cached: Boolean = false + def accept(l: Long) { cache = l; cached = true } + + private def loadCache: Boolean = sp.tryAdvance(this) + private def useCache(c: java.util.function.LongConsumer): Boolean = { + if (cached) { + c.accept(cache) + cached = false + true + } + else false + } + + def characteristics = sp.characteristics + def estimateSize = { + val sz = sp.estimateSize + if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 + else sz + } + override def forEachRemaining(c: java.util.function.LongConsumer) { + useCache(c) + sp.forEachRemaining(c) + } + def hasNext = cached || loadCache + def nextLong = { + if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + val ans = cache + cached = false + ans + } + def substep(): StepperLong = { + val subSp = sp.trySplit() + if (subSp eq null) null + else { + val sub = new OfLongSpliterator(subSp) + if (cached) { + sub.cache = cache + sub.cached = true + cached = false + } + sub + } + } + override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) + } def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) + def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) + def ofSpliterator(sp: java.util.Spliterator.OfLong) = new OfLongSpliterator(sp) } trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { From ec8ebd12afe048074880c275ecaddebcaedb18b3 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 29 Aug 2015 19:44:13 -0700 Subject: [PATCH 032/340] Work in progress on Filter etc.. --- .../compat/java8/collectionImpl/Stepper.scala | 109 +++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 8c7eb5f..0d7d0b1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,15 +1,49 @@ package scala.compat.java8.collectionImpl +/** A Stepper is a specialized collection that can step through its + * contents once. It provides the same test-and-get methods as + * does `Iterator`, named `hasStep` and `nextStep` so they can + * coexist with iterator methods. However, like `java.util.Spliterator`, + * steppers provide a `tryStep` method to call a closure if another + * element exists, a `substep()` method to split into pieces, and + * `characteristics` and size-reporting methods that + * implement the subdivision and report what is known about the remaining + * size of the `Stepper`. `Stepper` thus naturally implements both + * `Iterator` and `Spliterator`. + * + * Subtraits `NextStepper` and `TryStepper` fill in the basic capability + * by either implementing `tryStep` in terms of `hasStep` and `nextStep`, + * or vice versa. + * + * `Stepper` implements four core intermediate operations that process + * the sequence of elements and return another `Stepper`, and six core + * terminal operations that consume the `Stepper` and produce a result. + * If additional functionality is needed, one can convert a `Stepper` to + * a Scala `Iterator` or a Java 8 `Stream`. + */ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def characteristics: Int - def hasStep: Boolean def knownSize: Long - def nextStep: A + def hasStep: Boolean + def nextStep(): A def tryStep(f: A => Unit): Boolean def substep(): CC def typedPrecisely: CC + + //// + // Intermediate operations (do produce another Stepper) + //// + def drop(n: Int): Stepper[A, CC] + def filter(p: A => Boolean): Stepper[A, CC] + def flatMap[@specialized(Double, Int, Long) B, DD](f: A => Stepper[B, DD])(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = + impl.flatmapOf(this, f) + def map[@specialized(Double, Int, Long) B, DD](f: A => B)(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = + impl.mapOf(this, f) + def take(n: Int): Stepper[A, CC] + //// // Terminal operations (do not produce another Stepper) + //// def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } @@ -19,7 +53,34 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } } + +trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { + def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false +} + +trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { + private var myCache: A = null.asInstanceOf[A] + private var myCacheIsFull = false + private def load(): Boolean = { + myCacheIsFull = tryStep(myCache = _) + myCacheIsFull + } + def hasStep = myCacheIsFull || load() + def nextStep = { + if (!myCacheIsFull) { + load() + if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") + } + val ans = myCache + myCacheIsFull = false + myCache = null.asInstanceOf[A] + ans + } +} + + object Stepper { + class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) extends StepperGeneric[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] @@ -71,6 +132,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } + class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) extends StepperDouble with java.util.function.DoubleConsumer { private var cache: Double = Double.NaN @@ -119,6 +181,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) } + class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) extends StepperInt with java.util.function.IntConsumer { private var cache: Int = 0 @@ -167,6 +230,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) } + class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) extends StepperLong with java.util.function.LongConsumer { private var cache: Long = 0L @@ -215,6 +279,7 @@ object Stepper { } override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } + def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) @@ -230,6 +295,46 @@ trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Ite def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false def trySplit() = substep.typedPrecisely final def typedPrecisely: StepperGeneric[A] = this + + def filter(p: A => Boolean): StepperGeneric[A] = new FilteredStepperGeneric(this, p) +} + +trait FilteredStepperGeneric[A](orig: StepperGeneric[A], predicate: A => Boolean) extends StepperGeneric[A] { + private val knownComplete = false + private val myCache: A = null.asInstanceOf[A] + private val isCached = false + private var myOrig = orig + private var myPred = predicate + + private def loadCache(): Boolean = if (knownComplete) false else { + while (orig.hasNext) { + val temp = orig.next + if (predicate(temp)) { + isCached = true + myCache = temp + return true + } + } + false + } + + override def getExactSizeIfKnown = if (knownComplete) 0L else -1L + override def hasNext(): Boolean = isCached || loadCache + override def next(): A = + if (hasNext) { val ans = myCache; myCache = null.asInstanceOf[A]; isCached = false; ans } + else throw new NoSuchElementException("Out of elements in Stepper.next") + override def substep() = { + val ss = orig.substep() + if (ss == null) null + else { + val init = new FilteredStepperGeneric[A](ss, predicate) + init.myCache = myCache + init.isCached = isCached + myCache = null.asInstanceOf[A] + isCached = false + init + } + } } trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { From bc909f4efff00cdc2b81bab04581c3cde8a5e342 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 2 Sep 2015 16:25:19 -0700 Subject: [PATCH 033/340] Refactored names a bit, tried to make interface work a little better. --- .../compat/java8/SpliteratorConverters.scala | 8 +- .../scala/compat/java8/StepConverters.scala | 36 +-- .../compat/java8/collectionImpl/Stepper.scala | 221 ++++++++---------- 3 files changed, 116 insertions(+), 149 deletions(-) diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala index a8bc6fb..1babaf3 100644 --- a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -7,7 +7,7 @@ import scala.compat.java8.collectionImpl._ package SpliteratorConverters { class SpliteratorToStepper[A] private[java8] (private val underlying: Spliterator[A]) extends AnyVal { - def stepper: StepperGeneric[A] = Stepper.ofSpliterator(underlying) + def stepper: AnyStepper[A] = Stepper.ofSpliterator(underlying) } trait Priority2SpliteratorConverters { @@ -18,12 +18,12 @@ package SpliteratorConverters { package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { - def stepper: StepperDouble = Stepper.ofSpliterator(underlying) + def stepper: DoubleStepper = Stepper.ofSpliterator(underlying) } implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { - def stepper: StepperInt = Stepper.ofSpliterator(underlying) + def stepper: IntStepper = Stepper.ofSpliterator(underlying) } implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { - def stepper: StepperLong = Stepper.ofSpliterator(underlying) + def stepper: LongStepper = Stepper.ofSpliterator(underlying) } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ec95c35..2297a7d 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,12 +8,12 @@ package converterImpls { import StepConverters.SplitFlags._ private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) - extends StepperGeneric[A] { + extends AnyStepper[A] { def semiclone(half: Int): STA def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def substep(): StepperGeneric[A] = { + def substep(): AnyStepper[A] = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 val ans = semiclone(half) @@ -72,7 +72,7 @@ package converterImpls { def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) } - private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends StepperDouble { + private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -88,7 +88,7 @@ package converterImpls { } } - private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends StepperInt { + private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -104,7 +104,7 @@ package converterImpls { } } - private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends StepperLong { + private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { def characteristics() = NonNull + Sized + Subsized def estimateSize() = iN - i0 def hasNext() = i0 < iN @@ -121,38 +121,38 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: Stepper[A, StepperGeneric[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: Stepper[Unit, StepperGeneric[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: Stepper[Unit, AnyStepper[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: Stepper[Boolean, StepperGeneric[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: Stepper[Boolean, AnyStepper[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: Stepper[Byte, StepperGeneric[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: Stepper[Byte, AnyStepper[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: Stepper[Char, StepperGeneric[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: Stepper[Char, AnyStepper[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: Stepper[Short, StepperGeneric[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: Stepper[Short, AnyStepper[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: Stepper[Float, StepperGeneric[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: Stepper[Float, AnyStepper[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends StepperInt { + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 def hasNext = i0 < iN @@ -206,18 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: Stepper[Double, StepperDouble] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: Stepper[Double, DoubleStepper] = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: Stepper[Int, StepperInt] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, IntStepper] = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: Stepper[Long, StepperLong] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: Stepper[Long, LongStepper] = new StepperArrayLong(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: Stepper[Int, StepperInt] = new StepperStringCodePoint(underlying, 0, underlying.length) + @inline def stepper: Stepper[Int, IntStepper] = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 0d7d0b1..8a3acc6 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,9 +1,11 @@ package scala.compat.java8.collectionImpl +import java.util.Spliterator + /** A Stepper is a specialized collection that can step through its * contents once. It provides the same test-and-get methods as * does `Iterator`, named `hasStep` and `nextStep` so they can - * coexist with iterator methods. However, like `java.util.Spliterator`, + * coexist with iterator methods. However, like `Spliterator`, * steppers provide a `tryStep` method to call a closure if another * element exists, a `substep()` method to split into pieces, and * `characteristics` and size-reporting methods that @@ -11,17 +13,21 @@ package scala.compat.java8.collectionImpl * size of the `Stepper`. `Stepper` thus naturally implements both * `Iterator` and `Spliterator`. * + * A `Stepper` can present itself as a Spliterator via the `spliterator` + * method, or as a Scala Iterator via the `iterator` method. The `Stepper` + * trait is compatible with both `Spliterator` and Java's generic and + * primitive iterators, so a `Stepper` may already be one or both. + * * Subtraits `NextStepper` and `TryStepper` fill in the basic capability * by either implementing `tryStep` in terms of `hasStep` and `nextStep`, * or vice versa. * - * `Stepper` implements four core intermediate operations that process - * the sequence of elements and return another `Stepper`, and six core - * terminal operations that consume the `Stepper` and produce a result. - * If additional functionality is needed, one can convert a `Stepper` to - * a Scala `Iterator` or a Java 8 `Stream`. + * Subtraits `AnyStepper`, `DoubleStepper`, `IntStepper`, and `LongStepper` + * implement both the `Stepper` trait and the corresponding Java + * `Spliterator` and `Iterator`/`PrimitiveIterator`. */ -trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { + +trait Stepper[@specialized(Double, Int, Long) A, CC] { self => def characteristics: Int def knownSize: Long def hasStep: Boolean @@ -30,17 +36,6 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def substep(): CC def typedPrecisely: CC - //// - // Intermediate operations (do produce another Stepper) - //// - def drop(n: Int): Stepper[A, CC] - def filter(p: A => Boolean): Stepper[A, CC] - def flatMap[@specialized(Double, Int, Long) B, DD](f: A => Stepper[B, DD])(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = - impl.flatmapOf(this, f) - def map[@specialized(Double, Int, Long) B, DD](f: A => B)(implicit impl: StepImpl[A, B, CC, DD]): Stepper[B, DD] = - impl.mapOf(this, f) - def take(n: Int): Stepper[A, CC] - //// // Terminal operations (do not produce another Stepper) //// @@ -52,13 +47,22 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] extends Any { def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } def foreach(f: A => Unit) { while (hasStep) f(nextStep) } def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } + + //// + // Operations that convert to another related type + //// + def spliterator: Spliterator[A] + def iterator: Iterator[A] = new scala.collection.AbstractIterator[A] { + def hasNext = self.hasStep + def next = self.nextStep + } } -trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { +trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } -trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper[A, CC] { +trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false private def load(): Boolean = { @@ -77,12 +81,66 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Any with Stepper ans } } + +trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { + def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = next + def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false + def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: AnyStepper[A] = this + override def spliterator: Spliterator[A] = this +} + +trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextDouble + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false + def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false + def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely: DoubleStepper = this + override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double +} + +trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextInt + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false + def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false + def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this + override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int +} + +trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { + def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + def hasStep = hasNext() + def knownSize = getExactSizeIfKnown + def nextStep = nextLong + def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false + def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false + def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false + def trySplit() = substep.typedPrecisely + final def typedPrecisely = this + override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long +} object Stepper { - class OfSpliterator[A] private[java8] (sp: java.util.Spliterator[A]) - extends StepperGeneric[A] with java.util.function.Consumer[A] { + private class OfSpliterator[A](sp: Spliterator[A]) + extends AnyStepper[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] private var cached: Boolean = false def accept(a: A) { cache = a; cached = true } @@ -116,7 +174,7 @@ object Stepper { cached = false ans } - def substep(): StepperGeneric[A] = { + def substep(): AnyStepper[A] = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -133,8 +191,8 @@ object Stepper { override def tryAdvance(c: java.util.function.Consumer[_ >: A]) = useCache(c) || sp.tryAdvance(c) } - class OfDoubleSpliterator private[java8] (sp: java.util.Spliterator.OfDouble) - extends StepperDouble with java.util.function.DoubleConsumer { + private class OfDoubleSpliterator(sp: Spliterator.OfDouble) + extends DoubleStepper with java.util.function.DoubleConsumer { private var cache: Double = Double.NaN private var cached: Boolean = false def accept(d: Double) { cache = d; cached = true } @@ -166,7 +224,7 @@ object Stepper { cached = false ans } - def substep(): StepperDouble = { + def substep(): DoubleStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -182,8 +240,8 @@ object Stepper { override def tryAdvance(c: java.util.function.DoubleConsumer) = useCache(c) || sp.tryAdvance(c) } - class OfIntSpliterator private[java8] (sp: java.util.Spliterator.OfInt) - extends StepperInt with java.util.function.IntConsumer { + private class OfIntSpliterator(sp: Spliterator.OfInt) + extends IntStepper with java.util.function.IntConsumer { private var cache: Int = 0 private var cached: Boolean = false def accept(i: Int) { cache = i; cached = true } @@ -215,7 +273,7 @@ object Stepper { cached = false ans } - def substep(): StepperInt = { + def substep(): IntStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -231,8 +289,8 @@ object Stepper { override def tryAdvance(c: java.util.function.IntConsumer) = useCache(c) || sp.tryAdvance(c) } - class OfLongSpliterator private[java8] (sp: java.util.Spliterator.OfLong) - extends StepperLong with java.util.function.LongConsumer { + private class OfLongSpliterator(sp: Spliterator.OfLong) + extends LongStepper with java.util.function.LongConsumer { private var cache: Long = 0L private var cached: Boolean = false def accept(l: Long) { cache = l; cached = true } @@ -264,7 +322,7 @@ object Stepper { cached = false ans } - def substep(): StepperLong = { + def substep(): LongStepper = { val subSp = sp.trySplit() if (subSp eq null) null else { @@ -280,99 +338,8 @@ object Stepper { override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } - def ofSpliterator[A](sp: java.util.Spliterator[A]) = new OfSpliterator[A](sp) - def ofSpliterator(sp: java.util.Spliterator.OfDouble) = new OfDoubleSpliterator(sp) - def ofSpliterator(sp: java.util.Spliterator.OfInt) = new OfIntSpliterator(sp) - def ofSpliterator(sp: java.util.Spliterator.OfLong) = new OfLongSpliterator(sp) -} - -trait StepperGeneric[A] extends Stepper[A, StepperGeneric[A]] with java.util.Iterator[A] with java.util.Spliterator[A] { - def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = next - def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false - def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely: StepperGeneric[A] = this - - def filter(p: A => Boolean): StepperGeneric[A] = new FilteredStepperGeneric(this, p) -} - -trait FilteredStepperGeneric[A](orig: StepperGeneric[A], predicate: A => Boolean) extends StepperGeneric[A] { - private val knownComplete = false - private val myCache: A = null.asInstanceOf[A] - private val isCached = false - private var myOrig = orig - private var myPred = predicate - - private def loadCache(): Boolean = if (knownComplete) false else { - while (orig.hasNext) { - val temp = orig.next - if (predicate(temp)) { - isCached = true - myCache = temp - return true - } - } - false - } - - override def getExactSizeIfKnown = if (knownComplete) 0L else -1L - override def hasNext(): Boolean = isCached || loadCache - override def next(): A = - if (hasNext) { val ans = myCache; myCache = null.asInstanceOf[A]; isCached = false; ans } - else throw new NoSuchElementException("Out of elements in Stepper.next") - override def substep() = { - val ss = orig.substep() - if (ss == null) null - else { - val init = new FilteredStepperGeneric[A](ss, predicate) - init.myCache = myCache - init.isCached = isCached - myCache = null.asInstanceOf[A] - isCached = false - init - } - } + def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) } - -trait StepperDouble extends Stepper[Double, StepperDouble] with java.util.PrimitiveIterator.OfDouble with java.util.Spliterator.OfDouble { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } - def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextDouble - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false - def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false - def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - -trait StepperInt extends Stepper[Int, StepperInt] with java.util.PrimitiveIterator.OfInt with java.util.Spliterator.OfInt { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } - def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextInt - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false - def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false - def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - -trait StepperLong extends Stepper[Long, StepperLong] with java.util.PrimitiveIterator.OfLong with java.util.Spliterator.OfLong { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } - def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } - def hasStep = hasNext() - def knownSize = getExactSizeIfKnown - def nextStep = nextLong - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false - def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false - def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false - def trySplit() = substep.typedPrecisely - final def typedPrecisely = this -} - From 7b6e1180ec1fd21c8874d0bad2dc51c009024aab Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 6 Sep 2015 20:48:39 -0700 Subject: [PATCH 034/340] Added outline of a test for Stepper. --- .../compat/java8/collectionImpl/Stepper.scala | 121 +++++++++++++++++- .../scala/compat/java8/StepperTest.scala | 55 ++++++++ 2 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/test/scala/scala/compat/java8/StepperTest.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 8a3acc6..9fdf613 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -25,43 +25,132 @@ import java.util.Spliterator * Subtraits `AnyStepper`, `DoubleStepper`, `IntStepper`, and `LongStepper` * implement both the `Stepper` trait and the corresponding Java * `Spliterator` and `Iterator`/`PrimitiveIterator`. + * + * Example: + * {{{ + * val s = Stepper.of(Vector(1,2,3,4)) + * if (s.hasStep) println(s.nextStep) // Prints 1 + * println(s.tryStep(i => println(i*i))) // Prints 4, then true + * s.substep.foreach(println) // Prints 3 + * println(s.count(_ > 3)) // Prints 4 + * println(s.hasStep) // Prints `false` + * }}} */ trait Stepper[@specialized(Double, Int, Long) A, CC] { self => + /** Characteristics are bit flags that indicate runtime characteristics of this Stepper. + * + * - `Distinct` means that no duplicates exist + * - `Immutable` means that the underlying collection is guaranteed not to change during traversal + * - `NonNull` means that no nulls will be returned during traversal + * - `Sized` means that the collection knows its exact size + * - `SubSized` means that sub-Steppers created with `substep()` will also know their own size. `SubSized` steppers must also be `Sized`. + * + * The Java flags `CONCURRENT` and `SORTED` are not supported; modification of a concurrency-aware underlying collection is not + * guaranteed to be any safer than modification of any generic mutable collection, and if the underlying collection is ordered by + * virtue of sorting, `Stepper` will not keep track of that fact. + */ def characteristics: Int + + /** Returns the size of the collection, if known exactly, or `-1` if not. */ def knownSize: Long + + /** `true` if there are more elements to step through, `false` if not. */ def hasStep: Boolean + + /** The next element traversed by this Stepper. + * `nextStep()` throws an exception if no elements exist, so check `hasStep` immediately prior + * to calling. Note that `tryStep` also consumes an element, so the result of `hasStep` will + * be invalid after `tryStep` is called. + */ def nextStep(): A + + /** If another element exists, apply `f` to it and return `true`; otherwise, return `false`. */ def tryStep(f: A => Unit): Boolean + + /** Attempt to split this `Stepper` in half, with the new (returned) copy taking the first half + * of the collection, and this one advancing to cover the second half. If subdivision is not + * possible or not advisable, `substep()` will return `null`. + */ def substep(): CC + + /** Returns the precise underlying type of this `Stepper`. */ def typedPrecisely: CC + //// // Terminal operations (do not produce another Stepper) //// + + /** Consumes all remaining elements in this `Stepper` and counts how many there are. + * This is a terminal operation. + */ def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + + /** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`. + * This is a terminal operation. + */ def count(p: A => Boolean): Long = { var n = 0L; while (hasStep) { if (p(nextStep)) n += 1 }; n } + + /** Searches for an element that satisfies condition `p`. If none are found, it returns `false`. + * This is a terminal operation. + */ def exists(p: A => Boolean): Boolean = { while(hasStep) { if (p(nextStep)) return true }; false } + + /** Searches for an element that satisifes condition `p`, returning it wrapped in `Some` if one is found, or `None` otherwise. + * This is a terminal operation. + */ def find(p: A => Boolean): Option[A] = { while (hasStep) { val a = nextStep; if (p(a)) return Some(a) }; None } + + /** Repeatedly applies `op` to propagate an initial value `zero` through all elements of the collection. + * Traversal order is left-to-right. + * This is a terminal operation. + */ def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (hasStep) { b = op(b, nextStep) }; b } + + /** Repeatedly applies `op` to propagate an initial value `zero` through the collection until a condition `p` is met. + * If `p` is never met, the result of the last operation is returned. + * This is a terminal operation. + */ def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } + + /** Applies `f` to every remaining element in the collection. + * This is a terminal operation. + */ def foreach(f: A => Unit) { while (hasStep) f(nextStep) } - def reduce(f: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = f(a, nextStep) }; a } + + /** Repeatedly merges elements with `op` until only a single element remains. + * Throws an exception if the `Stepper` is empty. + * Merging occurs from left to right. + * This is a terminal operation. + */ + def reduce(op: (A, A) => A): A = { var a = nextStep; while (hasStep) { a = op(a, nextStep) }; a } + //// // Operations that convert to another related type //// + + /** Returns this `Stepper` as a `java.util.Spliterator`. + * This is a terminal operation. + */ def spliterator: Spliterator[A] + + /** Returns this `Stepper` as a Scala `Iterator`. + * This is a terminal operation. + */ def iterator: Iterator[A] = new scala.collection.AbstractIterator[A] { def hasNext = self.hasStep def next = self.nextStep } } +/** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } +/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false @@ -80,8 +169,10 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { myCache = null.asInstanceOf[A] ans } + override def foreach(f: A => Unit) { while(tryStep(f)) {} } } +/** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } def hasStep = hasNext() @@ -94,6 +185,7 @@ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] override def spliterator: Spliterator[A] = this } +/** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } @@ -108,6 +200,7 @@ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.Primit override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double } +/** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } @@ -122,6 +215,7 @@ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterat override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int } +/** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } @@ -138,6 +232,24 @@ trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIte object Stepper { + /** Indicates that a Stepper delivers distinct values (e.g. is backed by a `Set`) */ + val Distinct = Spliterator.DISTINCT + + /** Indicates that a Stepper runs over an immutable collection */ + val Immutable = Spliterator.IMMUTABLE + + /** Indicates that a Stepper will not return any `null` values */ + val NonNull = Spliterator.NONNULL + + /** Indicates that a Stepper delivers elements in a particular order that should be maintained */ + val Ordered = Spliterator.ORDERED + + /** Indicates that a Stepper knows exactly how many elements it contains */ + val Sized = Spliterator.SIZED + + /** Indicates that a Stepper's children (created with substep()) will all know their size. Steppers that are SubSized must also be Sized. */ + val SubSized = Spliterator.SUBSIZED + private class OfSpliterator[A](sp: Spliterator[A]) extends AnyStepper[A] with java.util.function.Consumer[A] { @@ -338,8 +450,15 @@ object Stepper { override def tryAdvance(c: java.util.function.LongConsumer) = useCache(c) || sp.tryAdvance(c) } + /** Creates a `Stepper` over a generic `Spliterator`. */ def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + + /** Creates a `Stepper` over a `DoubleSpliterator`. */ def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + + /** Creates a `Stepper` over an `IntSpliterator`. */ def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + + /** Creates a `Stepper` over a `LongSpliterator`. */ def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala new file mode 100644 index 0000000..1887cc8 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -0,0 +1,55 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StepperTest { + class IncStepperA(private val size0: Long) extends NextStepper[Int, IncStepperA] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def hasStep = i < knownSize + def nextStep() = { i += 1; (i - 1).toInt } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new FakeStepper1(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this + } + + class IncStepperB(private val size0: Long) extends TryStepper[Int, IncStepperB] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i); i += 1; true } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new FakeStepper1(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + def typedPrecisely = this + } + + def subs[Z, A, CC](zero: Z)(s: Stepper[A, CC], f: Stepper[A, CC] => Z, op: (Z, Z) => Z): Z = { + val ss = s.substep() + if (ss == null) op(zero, f(s)) + else { + val left = subs(zero)(ss, f, op) + subs(left)(s, f, op) + } + } + + val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) + def sources = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + + @Test + def count_only() { + sources.foreach{ case (i, s) => assertEquals(i, s.count) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s, _.count, _ + _)) } + } +} From 5f7d2d7f132bf0e6c4a16725834210f9dad1994d Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Sep 2015 23:23:17 -0700 Subject: [PATCH 035/340] Converted to covariant 2nd arg in Stepper, introduced StepperLike. --- .../scala/compat/java8/StepConverters.scala | 24 +++++++++---------- .../compat/java8/collectionImpl/Stepper.scala | 17 +++++++------ .../scala/compat/java8/StepperTest.scala | 24 +++++++++++-------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 2297a7d..21b0eeb 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -121,35 +121,35 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepperArrayGenAny[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: Stepper[A, AnyStepper[A]] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepperArrayGenObject[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: Stepper[Unit, AnyStepper[Unit]] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Unit] = new StepperArrayGenUnit(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: Stepper[Boolean, AnyStepper[Boolean]] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Boolean] = new StepperArrayGenBoolean(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: Stepper[Byte, AnyStepper[Byte]] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Byte] = new StepperArrayGenByte(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: Stepper[Char, AnyStepper[Char]] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Char] = new StepperArrayGenChar(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: Stepper[Short, AnyStepper[Short]] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Short] = new StepperArrayGenShort(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: Stepper[Float, AnyStepper[Float]] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Float] = new StepperArrayGenFloat(underlying, 0, underlying.length) } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { @@ -206,18 +206,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: Stepper[Double, DoubleStepper] = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: DoubleStepper = new StepperArrayDouble(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: Stepper[Int, IntStepper] = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepperArrayInt(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: Stepper[Long, LongStepper] = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: LongStepper = new StepperArrayLong(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: Stepper[Int, IntStepper] = new StepperStringCodePoint(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 9fdf613..301138a 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -36,8 +36,11 @@ import java.util.Spliterator * println(s.hasStep) // Prints `false` * }}} */ +trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} -trait Stepper[@specialized(Double, Int, Long) A, CC] { self => +/** Provides functionality for Stepper while keeping track of a more precise type of the collection. + */ +trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => /** Characteristics are bit flags that indicate runtime characteristics of this Stepper. * * - `Distinct` means that no duplicates exist @@ -146,12 +149,12 @@ trait Stepper[@specialized(Double, Int, Long) A, CC] { self => } /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ -trait NextStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { +trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ -trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { +trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { private var myCache: A = null.asInstanceOf[A] private var myCacheIsFull = false private def load(): Boolean = { @@ -173,7 +176,7 @@ trait TryStepper[@specialized(Double, Int, Long) A, CC] extends Stepper[A, CC] { } /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ -trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] with Spliterator[A] { +trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterator[A] with StepperLike[A, AnyStepper[A]] { def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown @@ -186,7 +189,7 @@ trait AnyStepper[A] extends Stepper[A, AnyStepper[A]] with java.util.Iterator[A] } /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ -trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble { +trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } def hasStep = hasNext() @@ -201,7 +204,7 @@ trait DoubleStepper extends Stepper[Double, DoubleStepper] with java.util.Primit } /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ -trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt { +trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt with StepperLike[Int, IntStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } def hasStep = hasNext() @@ -216,7 +219,7 @@ trait IntStepper extends Stepper[Int, IntStepper] with java.util.PrimitiveIterat } /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ -trait LongStepper extends Stepper[Long, LongStepper] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong { +trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong with StepperLike[Long, LongStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } def hasStep = hasNext() diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 1887cc8..57f9a36 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -3,8 +3,10 @@ package scala.compat.java8 import org.junit.Test import org.junit.Assert._ +import collectionImpl._ + class StepperTest { - class IncStepperA(private val size0: Long) extends NextStepper[Int, IncStepperA] { + class IncStepperA(private val size0: Long) extends NextStepper[Int] with StepperLike[Int, IncStepperA] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 @@ -12,44 +14,46 @@ class StepperTest { def hasStep = i < knownSize def nextStep() = { i += 1; (i - 1).toInt } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new FakeStepper1(size0 - (size0 - i)/2) + val sub = new IncStepperA(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub } def typedPrecisely = this + def spliterator = ??? } - class IncStepperB(private val size0: Long) extends TryStepper[Int, IncStepperB] { + class IncStepperB(private val size0: Long) extends TryStepper[Int] with StepperLike[Int, IncStepperB] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i); i += 1; true } + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new FakeStepper1(size0 - (size0 - i)/2) + val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub } def typedPrecisely = this + def spliterator = ??? } - def subs[Z, A, CC](zero: Z)(s: Stepper[A, CC], f: Stepper[A, CC] => Z, op: (Z, Z) => Z): Z = { + def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() if (ss == null) op(zero, f(s)) else { - val left = subs(zero)(ss, f, op) - subs(left)(s, f, op) + val left = subs(zero)(ss)(f, op) + subs(left)(s)(f, op) } } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } - sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s, _.count, _ + _)) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } } } From 649dec44f2174348a7f12e14038cc6d0331a72ff Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Sep 2015 23:42:46 -0700 Subject: [PATCH 036/340] Moved classes outside of StepperTest to see if this helps exception. --- .../scala/compat/java8/StepperTest.scala | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 57f9a36..f028bc5 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -5,40 +5,40 @@ import org.junit.Assert._ import collectionImpl._ -class StepperTest { - class IncStepperA(private val size0: Long) extends NextStepper[Int] with StepperLike[Int, IncStepperA] { - if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") - private var i = 0L - def characteristics = 0 - def knownSize = math.max(0L, size0 - i) - def hasStep = i < knownSize - def nextStep() = { i += 1; (i - 1).toInt } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(size0 - (size0 - i)/2) - sub.i = i - i = sub.size0 - sub - } - def typedPrecisely = this - def spliterator = ??? +class IncStepperA(private val size0: Long) extends NextStepper[Int] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def hasStep = i < knownSize + def nextStep() = { i += 1; (i - 1).toInt } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub } + def typedPrecisely = this + def spliterator = ??? +} - class IncStepperB(private val size0: Long) extends TryStepper[Int] with StepperLike[Int, IncStepperB] { - if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") - private var i = 0L - def characteristics = 0 - def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperB(size0 - (size0 - i)/2) - sub.i = i - i = sub.size0 - sub - } - def typedPrecisely = this - def spliterator = ??? +class IncStepperB(private val size0: Long) extends TryStepper[Int] { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = 0 + def knownSize = math.max(0L, size0 - i) + def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } + def substep() = if ((knownSize - i) <= 1) null else { + val sub = new IncStepperB(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub } + def typedPrecisely = this + def spliterator = ??? +} +class StepperTest { def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() if (ss == null) op(zero, f(s)) From e6c8ffa98cd0b360f223a0efd549ce3777086eb8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 8 Sep 2015 00:24:50 -0700 Subject: [PATCH 037/340] Fixed TryStepper impl to avoid specialization bug. Added tests. --- .../compat/java8/collectionImpl/Stepper.scala | 3 +- .../scala/compat/java8/StepperTest.scala | 45 ++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 301138a..5fb23d4 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -155,7 +155,8 @@ trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Ste /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { - private var myCache: A = null.asInstanceOf[A] + protected def myCache: A + protected def myCache_=(a: A): Unit private var myCacheIsFull = false private def load(): Boolean = { myCacheIsFull = tryStep(myCache = _) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index f028bc5..78c26e4 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -5,15 +5,16 @@ import org.junit.Assert._ import collectionImpl._ + class IncStepperA(private val size0: Long) extends NextStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) - def hasStep = i < knownSize + def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(size0 - (size0 - i)/2) + val sub = new IncStepperA(i + (size0 - i)/2) sub.i = i i = sub.size0 sub @@ -24,6 +25,7 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { class IncStepperB(private val size0: Long) extends TryStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + protected var myCache: Int = 0 private var i = 0L def characteristics = 0 def knownSize = math.max(0L, size0 - i) @@ -56,4 +58,43 @@ class StepperTest { sources.foreach{ case (i, s) => assertEquals(i, s.count) } sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } } + + @Test + def count_conditionally() { + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), s.count(_ % 3 == 0)) } + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), subs(0)(s)(_.count(_ % 3 == 0).toInt, _ + _)) } + } + + @Test + def existence() { + sources.foreach{ case (i, s) => assert(i > 0 == s.exists(_ >= 0)) } + sources.foreach{ case (i, s) => assert(i > 16 == s.exists(_ % 17 == 16)) } + sources.foreach{ case (i, s) => assert(i > 0 == subs(false)(s)(_.exists(_ >= 0), _ || _)) } + sources.foreach{ case (i, s) => assert(i > 16 == subs(false)(s)(_.exists(_ % 17 == 16), _ || _)) } + } + + @Test + def finding() { + for (k <- 0 until 100) { + (sources zip sources).foreach{ case ((i,s), (j,t)) => + val x = util.Random.nextInt(math.min(i,j)+3) + val a = s.find(_ == x) + val b = subs(None: Option[Int])(t)(_.find(_ == x), _ orElse _) + assertEquals(a, b) + assertEquals(a.isDefined, x < math.min(i,j)) + } + } + } + + @Test + def folding() { + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, s.fold("")(_ + _.toString)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, subs("")(s)(_.fold("")(_ + _.toString), _ + _)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, s.fold(0.0)(_ + _), 1e-10) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, subs(0.0)(s)(_.fold(0.0)(_ + _), _ + _), 1e-10) } + } + + @Test + def partialFolding() { + } } From 2550aff2fcbe1587ae51a5db8ae11f50ba638962 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 9 Sep 2015 15:10:44 -0700 Subject: [PATCH 038/340] Finished testing terminal operations for Stepper, save spliterator which isn't written. --- .../compat/java8/collectionImpl/Stepper.scala | 2 +- .../scala/compat/java8/StepperTest.scala | 41 ++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 5fb23d4..ee426c7 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -115,7 +115,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => * If `p` is never met, the result of the last operation is returned. * This is a terminal operation. */ - def foldUntil[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (p(b) && hasStep) { b = op(b, nextStep) }; b } + def foldTo[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (!p(b) && hasStep) { b = op(b, nextStep) }; b } /** Applies `f` to every remaining element in the collection. * This is a terminal operation. diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 78c26e4..565190a 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -95,6 +95,45 @@ class StepperTest { } @Test - def partialFolding() { + def foldingUntil() { + def expected(i: Int) = (0 until i).scan(0)(_ + _).dropWhile(_ < 6*i).headOption.getOrElse((0 until i).sum) + sources.foreach{ case (i,s) => assertEquals(expected(i), s.foldTo(0)(_ + _)(_ >= 6*i)) } + sources.foreach{ case (_,s) => assertEquals(-1, s.foldTo(-1)(_ * _)(_ => true)) } + sources.foreach{ case (i,s) => + val ss = s.substep + val x = s.foldTo( if (ss == null) 0 else ss.foldTo(0)(_ + _)(_ >= 6*i) )(_ + _)(_ >= 6*i) + assertEquals(expected(i), x) + } + } + + @Test + def foreaching() { + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + s.foreach( clq add _.toString ) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + subs(())(s)(_.foreach( clq add _.toString ), (_, _) => ()) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + } + + @Test + def reducing() { + sources.foreach{ case (i,s) => + if (i==0) assertEquals(s.hasStep, false) + else assertEquals((0 until i).sum, s.reduce(_ + _)) + } + sources.foreach{ case (i,s) => + assertEquals((0 until i).sum, subs(0)(s)(x => if (!x.hasStep) 0 else x.reduce(_ + _), _ + _)) + } + } + + @Test + def iterating() { + sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } } } + From 6ee09efd79fc2b64a089928ff4f85530b944da35 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 11:48:51 -0700 Subject: [PATCH 039/340] Added proxy-to-spliterator to default Stepper trait. (Should overrride everywhere important.) --- .../compat/java8/collectionImpl/Stepper.scala | 19 +++++++++++++++++-- .../scala/compat/java8/StepperTest.scala | 15 +++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index ee426c7..096eef4 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -149,12 +149,19 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => } /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ -trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { +trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false + def spliterator: Spliterator[A] = new ProxySpliteratorViaNext[A](this) +} +private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper[A]) extends Spliterator[A] { + def characteristics() = underlying.characteristics + def estimateSize() = underlying.knownSize + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = if (underlying.hasStep) { f.accept(underlying.nextStep()); true } else false + def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaNext[A](x) } } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ -trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { +trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A protected def myCache_=(a: A): Unit private var myCacheIsFull = false @@ -174,6 +181,14 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step ans } override def foreach(f: A => Unit) { while(tryStep(f)) {} } + def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this) +} +private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] { + def characteristics() = underlying.characteristics + def estimateSize() = underlying.knownSize + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryStep(a => f.accept(a)) + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { underlying.foreach(a => f.accept(a)) } + def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaTry[A](x) } } /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 565190a..abde749 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -20,7 +20,6 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { sub } def typedPrecisely = this - def spliterator = ??? } class IncStepperB(private val size0: Long) extends TryStepper[Int] { @@ -37,7 +36,6 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { sub } def typedPrecisely = this - def spliterator = ??? } class StepperTest { @@ -135,5 +133,18 @@ class StepperTest { def iterating() { sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } } + + @Test + def spliterating() { + sources.foreach{ case (i,s) => + var sum = 0 + s.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sum += i } }) + assertEquals(sum, (0 until i).sum) + } + sources.foreach{ case (i,s) => + val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sm += i } }); sm }, _ + _) + assertEquals(sum, (0 until i).sum) + } + } } From 37ea39cc478092c4b036de35f4da97e8f91d7dbb Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 13:22:24 -0700 Subject: [PATCH 040/340] Tests on all the various permutations of Stepper-Spliterator converters. --- .../scala/compat/java8/StepperTest.scala | 88 ++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index abde749..75070c3 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -3,13 +3,15 @@ package scala.compat.java8 import org.junit.Test import org.junit.Assert._ +import java.util.Spliterator + import collectionImpl._ class IncStepperA(private val size0: Long) extends NextStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L - def characteristics = 0 + def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } @@ -26,7 +28,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") protected var myCache: Int = 0 private var i = 0L - def characteristics = 0 + def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { @@ -38,6 +40,78 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { def typedPrecisely = this } +class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { + private var i = 0L + def characteristics() = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + def estimateSize() = math.max(0L, size0 - i) + def tryAdvance(f: java.util.function.IntConsumer): Boolean = if (i >= size0) false else { f.accept(i.toInt); i += 1; true } + def trySplit(): Spliterator.OfInt = if (i+1 >= size0) null else { + val sub = new IncSpliterator(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + override def forEachRemaining(f: java.util.function.IntConsumer) { while (i < size0) { f.accept(i.toInt); i += 1 } } +} + +class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, Int, Long) B](underlying: Stepper[A], mapping: A => B) extends Stepper[B] { + def characteristics = underlying.characteristics + def knownSize = underlying.knownSize + def hasStep = underlying.hasStep + def nextStep() = mapping(underlying.nextStep()) + def tryStep(f: B => Unit): Boolean = underlying.tryStep(a => f(mapping(a))) + override def foreach(f: B => Unit) { underlying.foreach(a => f(mapping(a))) } + def substep() = { + val undersub = underlying.substep() + if (undersub == null) null + else new MappingStepper(undersub, mapping) + } + def typedPrecisely = this + def spliterator: Spliterator[B] = new MappingSpliterator[A, B](underlying.spliterator, mapping) +} + +class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: A => B) extends Spliterator[B] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: B]): Boolean = underlying.tryAdvance(new java.util.function.Consumer[A]{ def accept(a: A) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[B] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new MappingSpliterator(undersplit, mapping) + } +} +class IntToGenericSpliterator[A](private val underlying: Spliterator.OfInt, mapping: Int => A) extends Spliterator[A] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[A] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToGenericSpliterator[A](undersplit, mapping) + } +} +class IntToDoubleSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Double) extends Spliterator.OfDouble { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfDouble = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToDoubleSpliterator(undersplit, mapping) + } +} +class IntToLongSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Long) extends Spliterator.OfLong { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.LongConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfLong = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToLongSpliterator(undersplit, mapping) + } +} + + class StepperTest { def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { val ss = s.substep() @@ -49,7 +123,15 @@ class StepperTest { } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector(i -> new IncStepperA(i), i -> new IncStepperB(i))) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector( + i -> new IncStepperA(i), + i -> new IncStepperB(i), + i -> Stepper.ofSpliterator(new IncSpliterator(i)), + i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), + i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), + i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), + i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + )) @Test def count_only() { From 04bc02ae7823eb67f19d23502cfe3df396e0db1f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 16:54:14 -0700 Subject: [PATCH 041/340] Fixed a bug in tryStep of TryStepper by adding a protected tryUncached method. --- .../compat/java8/collectionImpl/Stepper.scala | 39 ++++++++++---- .../scala/compat/java8/StepperTest.scala | 52 ++++++++++++++++++- 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 096eef4..6f2edc1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -160,17 +160,20 @@ private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaNext[A](x) } } -/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. */ +/** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. + * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected. + * For speed, `foreachUncached` may also be overridden. + */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A protected def myCache_=(a: A): Unit - private var myCacheIsFull = false + protected final var myCacheIsFull = false private def load(): Boolean = { myCacheIsFull = tryStep(myCache = _) myCacheIsFull } - def hasStep = myCacheIsFull || load() - def nextStep = { + final def hasStep = myCacheIsFull || load() + final def nextStep = { if (!myCacheIsFull) { load() if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") @@ -180,7 +183,10 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step myCache = null.asInstanceOf[A] ans } - override def foreach(f: A => Unit) { while(tryStep(f)) {} } + final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f) + protected def tryUncached(f: A => Unit): Boolean + final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } + protected def foreachUncached(f: A => Unit) { while (tryUncached(f)) {} } def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this) } private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] { @@ -470,14 +476,29 @@ object Stepper { } /** Creates a `Stepper` over a generic `Spliterator`. */ - def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = new OfSpliterator[A](sp) + def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = sp match { + case as: AnyStepper[A] => as + case _ => new OfSpliterator[A](sp) + } + /** Creates a `Stepper` over a `DoubleSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = new OfDoubleSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfDouble): DoubleStepper = sp match { + case ds: DoubleStepper => ds + case _ => new OfDoubleSpliterator(sp) + } /** Creates a `Stepper` over an `IntSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfInt): IntStepper = new OfIntSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfInt): IntStepper = sp match { + case is: IntStepper => is + case _ => new OfIntSpliterator(sp) + } + /** Creates a `Stepper` over a `LongSpliterator`. */ - def ofSpliterator(sp: Spliterator.OfLong): LongStepper = new OfLongSpliterator(sp) + def ofSpliterator(sp: Spliterator.OfLong): LongStepper = sp match { + case ls: LongStepper => ls + case _ => new OfLongSpliterator(sp) + } + } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 75070c3..bae0d72 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -30,7 +30,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { private var i = 0L def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def knownSize = math.max(0L, size0 - i) - def tryStep(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } + protected def tryUncached(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } def substep() = if ((knownSize - i) <= 1) null else { val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i @@ -133,6 +133,56 @@ class StepperTest { i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) )) + @Test + def stepping() { + sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep == j } && !s.hasStep) } + sources.foreach{ case (i, s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while (x.hasStep) { val y = x.nextStep; assert(!(set contains y)); set += y } + 0 + }, + _ + _ + ) + assert((0 until i).toSet == set) + } + } + + @Test + def trying() { + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + while (s.tryStep{ y => assert(!(set contains y)); set += y }) {} + assert((0 until i).toSet == set) + } + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while(x.tryStep{ y => assert(!(set contains y)); set += y }) {} + 0 + }, + _ + _ + ) + assertTrue(s.getClass.getName + s" said [0, $i) was " + set.mkString("{", " ", "}"), (0 until i).toSet == set) + } + } + + @Test + def substepping() { + sources.foreach{ case (i,s) => + val ss = s.substep + assertEquals(ss == null, i < 2) + if (ss != null) { + assertTrue(s.hasStep) + assertTrue(ss.hasStep) + assertEquals(i, s.count + ss.count) + } + else assertEquals(i, s.count) + } + } + @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } From e7033e34c075cd7ce447667576b8ab7fdfd0f8c8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 12 Sep 2015 18:55:51 -0700 Subject: [PATCH 042/340] Finished tests of basic steppers and fixed bugs in TryStepper. --- .../compat/java8/collectionImpl/Stepper.scala | 15 +++-- .../scala/compat/java8/StepperTest.scala | 62 ++++++++++++++----- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 6f2edc1..3e09ee5 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -86,9 +86,13 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => //// /** Consumes all remaining elements in this `Stepper` and counts how many there are. - * This is a terminal operation. + * This is a terminal operation, though if `knownSize` is non-negative, it won't actually + * iterate over the elements. */ - def count(): Long = { var n = 0L; while (hasStep) { nextStep; n += 1 }; n } + def count(): Long = knownSize match { + case x if x < 0 => var n = 0L; while (hasStep) { nextStep; n += 1 }; n + case x => x + } /** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`. * This is a terminal operation. @@ -161,8 +165,9 @@ private[collectionImpl] class ProxySpliteratorViaNext[A](underlying: NextStepper } /** This trait indicates that a `Stepper` will implement `hasNext` and `nextStep` by caching applications of `tryStep`. - * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected. - * For speed, `foreachUncached` may also be overridden. + * Subclasses must implement `tryUncached` instead of `tryStep`, and should leave it protected, and must implement + * `knownUncachedSize` instead of `knownSize`. For speed, `foreachUncached` may also be overridden. It is recommended + * that all of the `Uncached` methods be left protected. */ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, TryStepper[A]] { protected def myCache: A @@ -183,6 +188,8 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step myCache = null.asInstanceOf[A] ans } + final def knownSize = knownUncachedSize + (if (myCacheIsFull) 1 else 0) + protected def knownUncachedSize: Long final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f) protected def tryUncached(f: A => Unit): Boolean final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index bae0d72..18cbc10 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -15,8 +15,8 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { def knownSize = math.max(0L, size0 - i) def hasStep = i < size0 def nextStep() = { i += 1; (i - 1).toInt } - def substep() = if ((knownSize - i) <= 1) null else { - val sub = new IncStepperA(i + (size0 - i)/2) + def substep() = if (knownSize <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) sub.i = i i = sub.size0 sub @@ -29,9 +29,9 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { protected var myCache: Int = 0 private var i = 0L def characteristics = Stepper.Sized | Stepper.SubSized | Stepper.Ordered - def knownSize = math.max(0L, size0 - i) + def knownUncachedSize = math.max(0L, size0 - i) protected def tryUncached(f: Int => Unit): Boolean = if (i >= size0) false else { f(i.toInt); i += 1; true } - def substep() = if ((knownSize - i) <= 1) null else { + def substep() = if (knownSize <= 1) null else { val sub = new IncStepperB(size0 - (size0 - i)/2) sub.i = i i = sub.size0 @@ -41,6 +41,7 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { } class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") private var i = 0L def characteristics() = Stepper.Sized | Stepper.SubSized | Stepper.Ordered def estimateSize() = math.max(0L, size0 - i) @@ -123,15 +124,27 @@ class StepperTest { } val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) - def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap(i => Vector( - i -> new IncStepperA(i), - i -> new IncStepperB(i), - i -> Stepper.ofSpliterator(new IncSpliterator(i)), - i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), - i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), - i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), - i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) - )) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap{ i => + Vector( + i -> new IncStepperA(i), + i -> new IncStepperB(i), + i -> Stepper.ofSpliterator(new IncSpliterator(i)), + i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), + i -> new MappingStepper[Long, Int](Stepper.ofSpliterator(new IntToLongSpliterator(new IncSpliterator(i), _.toLong)), _.toInt), + i -> new MappingStepper[Double, Int](Stepper.ofSpliterator(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)), _.toInt), + i -> new MappingStepper[String, Int](Stepper.ofSpliterator(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + ) ++ + { + // Implicitly converted instead of explicitly + import SpliteratorConverters._ + Vector[(Int, Stepper[Int])]( + i -> (new IncSpliterator(i)).stepper, + i -> new MappingStepper[Long, Int]((new IntToLongSpliterator(new IncSpliterator(i), _.toLong)).stepper, _.toInt), + i -> new MappingStepper[Double, Int]((new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble)).stepper, _.toInt), + i -> new MappingStepper[String, Int]((new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)).stepper, _.toInt) + ) + } + } @Test def stepping() { @@ -177,12 +190,33 @@ class StepperTest { if (ss != null) { assertTrue(s.hasStep) assertTrue(ss.hasStep) - assertEquals(i, s.count + ss.count) + val c1 = s.count + val c2 = ss.count + assertEquals(s"$i != $c1 + $c2 from ${s.getClass.getName}", i, c1 + c2) } else assertEquals(i, s.count) } } + @Test + def characteristically() { + val expected = Stepper.Sized | Stepper.SubSized | Stepper.Ordered + sources.foreach{ case (_,s) => assertEquals(s.characteristics, expected)} + sources.foreach{ case (_,s) => subs(0)(s)(x => { assertEquals(x.characteristics, expected); 0 }, _ + _) } + } + + @Test + def knownSizes() { + sources.foreach{ case (i,s) => assertEquals(i.toLong, s.knownSize) } + sources.foreach{ case (i,s) => if (i > 0) subs(0)(s)(x => { assertEquals(x.knownSize, 1L); 0 }, _ + _) } + } + + @Test + def consistentPrecision() { + sources.foreach{ case (_,s) => assert(s eq s.typedPrecisely) } + sources.foreach{ case (_,s) => subs(0)(s)(x => { assert(x eq x.typedPrecisely); 0}, _ + _) } + } + @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } From 6baf83269e509160b2d7cb90daaf61c921ff73a0 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 13 Jul 2015 16:13:56 -0700 Subject: [PATCH 043/340] Basic interoperability between Java8 Streams and Scala collections. This consists of (1) toScala[Coll] extension methods for Java8 Streams (2) seqStream and parStream extension methods for Scala collections (3) A manually specialized set of Accumulators that let you quickly save a stream for multiple re-use. (a) accumulate and accumulatePrimitive methods on Java8 Streams (b) to[Coll] on Accumulators (c) .iterator, .toArray, .toList also There is a lot of redundant code in the Accumulators since it is difficult to pull out common functionality without endangering performance of the manually specialized cases. Everything goes through the new Stepper trait to partially tame the Spliterator hierarchy. At this point, Scala collections all go through Accumulator. Need to write something custom for the more important collections. Tests written. Scaladocs written for the new classes. --- .../scala/compat/java8/StreamConverters.scala | 226 ++++++++++++ .../java8/collectionImpl/Accumulator.scala | 337 +++++++++++++++++ .../collectionImpl/AccumulatorLike.scala | 41 +++ .../collectionImpl/DoubleAccumulator.scala | 332 +++++++++++++++++ .../java8/collectionImpl/IntAccumulator.scala | 339 ++++++++++++++++++ .../collectionImpl/LongAccumulator.scala | 333 +++++++++++++++++ .../compat/java8/StreamConvertersTest.scala | 145 ++++++++ 7 files changed, 1753 insertions(+) create mode 100644 src/main/scala/scala/compat/java8/StreamConverters.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala create mode 100644 src/test/scala/scala/compat/java8/StreamConvertersTest.scala diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala new file mode 100644 index 0000000..0b9b644 --- /dev/null +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -0,0 +1,226 @@ +package scala.compat.java8 + +import language.implicitConversions + +import java.util.stream._ +import scala.compat.java8.collectionImpl._ + +trait PrimitiveStreamAccumulator[S, AA] { + def streamAccumulate(stream: S): AA +} + +trait PrimitiveStreamUnboxer[A, S] { + def apply(boxed: Stream[A]): S +} + +trait Priority2StreamConverters { + implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { + private def mkAcc() = { + val acc = new Accumulator[A] + t.foreach{ acc += _ } + acc + } + + def seqStream: Stream[A] = mkAcc().seqStream + + def parStream: Stream[A] = mkAcc().parStream + } + + implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { + private def mkAcc() = { + val acc = new Accumulator[A] + var i = 0 + while (i < a.length) { + acc += a(i) + i += 1 + } + acc + } + + def seqStream: Stream[A] = mkAcc().seqStream + + def parStream: Stream[A] = mkAcc().parStream + } +} + +trait Priority1StreamConverters extends Priority2StreamConverters { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + if (t.isTraversableAgain && t.hasDefiniteSize) { + val sz = t.size + val a = new Array[A](sz) + t.copyToArray(a, 0, sz) + a + } + else t.toArray[A] + } + + def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = + java.util.Arrays.stream(mkArr()) + + def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + } + + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { + def seqStream: Stream[A] = java.util.Arrays.stream(a) + def parStream: Stream[A] = seqStream.parallel + } + + implicit class RichStream[A](stream: Stream[A]) { + def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.Consumer[A]{ def accept(a: A) { b += a } }) + b.result() + } + } + + def unboxed[S](implicit ubx: PrimitiveStreamUnboxer[A, S]): S = ubx(stream) + } + + implicit class RichStreamCanAccumulatePrimitive[S](stream: S) { + def accumulatePrimitive[AA](implicit psa: PrimitiveStreamAccumulator[S, AA]) = psa.streamAccumulate(stream) + } +} + +/** `StreamConverters` provides extension methods and other functionality to + * ease interoperability of Scala collections with `java.util.stream` classes. + * + * Scala collections gain extension methods `seqStream` and + * `parStream` that allow them to be used as the source of a `Stream`. + * + * `Array` also gains `seqStream` and `parStream` methods, and calling those + * on `Array[Double]`, `Array[Int]`, or `Array[Long]` will produce the + * corresponding primitive stream. + * + * Streams gain `accumulate` and `toScala[_]` methods, which collect the stream + * into a custom high-performance `scala.collection.mutable.java8.Accumulator`, + * which is not part of the standard collections hierarchy, or into a named + * Scala collection, respectively. + * + * Generic streams also gain an `unboxed` method that will convert to the + * corresponding unboxed primitive stream, if appropriate. Unboxed streams + * have custom accumulators with improved performance. + * + * Accumulators have `toArray`, `toList`, `iterator`, and `to[_]` methods + * to convert to standard Scala collections. + * + * Example: + * ``` + * import scala.compat.java8.StreamConverers._ + * + * val s = Vector(1,2,3,4).parStream // Stream[Int] + * val si = s.unboxed // Stream.OfInt + * val ai = si.accumulate // IntAccumulator + * val v = ai.to[Vector] // Vector[Int] again + * + * val t = Array(2.0, 3.0, 4.0).parStream // DoubleStream + * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] + * ``` + */ +object StreamConverters extends Priority1StreamConverters { + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { + def seqStream: DoubleStream = java.util.Arrays.stream(a) + def parStream: DoubleStream = seqStream.parallel + } + + implicit class EnrichIntArrayWithStream(a: Array[Int]) { + def seqStream: IntStream = java.util.Arrays.stream(a) + def parStream: IntStream = seqStream.parallel + } + + implicit class EnrichLongArrayWithStream(a: Array[Long]) { + def seqStream: LongStream = java.util.Arrays.stream(a) + def parStream: LongStream = seqStream.parallel + } + + implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { + def streamAccumulate(stream: Stream[Double]): DoubleAccumulator = + stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger) + } + + implicit val primitiveAccumulateDoubleStream2 = + primitiveAccumulateDoubleStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Double], DoubleAccumulator]] + + implicit val primitiveUnboxDoubleStream = new PrimitiveStreamUnboxer[Double, DoubleStream] { + def apply(boxed: Stream[Double]): DoubleStream = + boxed.mapToDouble(new java.util.function.ToDoubleFunction[Double]{ def applyAsDouble(d: Double) = d }) + } + + implicit val primitiveUnboxDoubleStream2 = + primitiveUnboxDoubleStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Double, DoubleStream]] + + implicit val primitiveAccumulateIntStream = new PrimitiveStreamAccumulator[Stream[Int], IntAccumulator] { + def streamAccumulate(stream: Stream[Int]): IntAccumulator = + stream.collect(IntAccumulator.supplier, IntAccumulator.boxedAdder, IntAccumulator.merger) + } + + implicit val primitiveAccumulateIntStream2 = + primitiveAccumulateIntStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Integer], IntAccumulator]] + + implicit val primitiveUnboxIntStream = new PrimitiveStreamUnboxer[Int, IntStream] { + def apply(boxed: Stream[Int]): IntStream = + boxed.mapToInt(new java.util.function.ToIntFunction[Int]{ def applyAsInt(d: Int) = d }) + } + + implicit val primitiveUnboxIntStream2 = + primitiveUnboxIntStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Integer, IntStream]] + + implicit val primitiveAccumulateLongStream = new PrimitiveStreamAccumulator[Stream[Long], LongAccumulator] { + def streamAccumulate(stream: Stream[Long]): LongAccumulator = + stream.collect(LongAccumulator.supplier, LongAccumulator.boxedAdder, LongAccumulator.merger) + } + + implicit val primitiveAccumulateLongStream2 = + primitiveAccumulateLongStream.asInstanceOf[PrimitiveStreamAccumulator[Stream[java.lang.Long], LongAccumulator]] + + implicit val primitiveUnboxLongStream = new PrimitiveStreamUnboxer[Long, LongStream] { + def apply(boxed: Stream[Long]): LongStream = + boxed.mapToLong(new java.util.function.ToLongFunction[Long]{ def applyAsLong(d: Long) = d }) + } + + implicit val primitiveUnboxLongStream2 = + primitiveUnboxLongStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Long, LongStream]] + + implicit class RichDoubleStream(stream: DoubleStream) { + def accumulate = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.DoubleConsumer{ def accept(d: Double) { b += d } }) + b.result() + } + } + } + + implicit class RichIntStream(stream: IntStream) { + def accumulate = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.IntConsumer{ def accept(d: Int) { b += d } }) + b.result() + } + } + } + + implicit class RichLongStream(stream: LongStream) { + def accumulate = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) + + def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { + if (stream.isParallel) accumulate.to[Coll](cbf) + else { + val b = cbf() + stream.forEachOrdered(new java.util.function.LongConsumer{ def accept(d: Long) { b += d } }) + b.result() + } + } + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala new file mode 100644 index 0000000..b28790c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -0,0 +1,337 @@ +package scala.compat.java8.collectionImpl + +/** An `Accumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging Accumulators. + * Accumulators can contain more than `Int.MaxValue` elements. + */ +final class Accumulator[A] extends AccumulatorLike[A, Accumulator[A]] { self => + private[java8] var current: Array[AnyRef] = Accumulator.emptyAnyRefArray + private[java8] var history: Array[Array[AnyRef]] = Accumulator.emptyAnyRefArrayArray + private[java8] var cumul: Array[Long] = Accumulator.emptyLongArray + + private[java8] def cumulative(i: Int) = cumul(i) + + private def expand(): Unit = { + if (index > 0) { + if (hIndex >= history.length) hExpand() + history(hIndex) = current + cumul(hIndex) = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index + hIndex += 1 + } + current = new Array[AnyRef](nextBlockSize) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) { + history = new Array[Array[AnyRef]](4) + cumul = new Array[Long](4) + } + else { + history = java.util.Arrays.copyOf(history, history.length << 1) + cumul = java.util.Arrays.copyOf(cumul, cumul.length << 1) + } + } + + /** Appends an element to this `Accumulator`. */ + final def +=(a: A): Unit = { + totalSize += 1 + if (index >= current.length) expand() + current(index) = a.asInstanceOf[AnyRef] + index += 1 + } + + /** Removes all elements from `that` and appends them to this `Accumulator`. */ + final def drain[A1 <: A](that: Accumulator[A1]): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val n = (that.cumulative(h) - prev).toInt + if (current.length - index >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = that.cumulative(h) + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index >= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + cumul = java.util.Arrays.copyOf(cumul, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + pv += index + cumul(hIndex) = pv + history(hIndex) = (if (index < (current.length >>> 3) && current.length > 32) java.util.Arrays.copyOf(current, index) else current) + hIndex += 1 + } + while (h < that.hIndex) { + pv += that.cumulative(h) - prev + prev = that.cumulative(h) + cumul(hIndex) = pv + history(hIndex) = that.history(h) + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = Accumulator.emptyAnyRefArray + history = Accumulator.emptyAnyRefArrayArray + cumul = Accumulator.emptyLongArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): A = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt).asInstanceOf[A] + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt).asInstanceOf[A] + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): A = apply(i.toLong) + + /** Returns a `Stepper` over the contents of this `Accumulator`*/ + final def stepper: AnyStepper[A] = new AccumulatorStepper[A](this) + + /** Returns an `Iterator` over the contents of this `Accumulator`. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator` over the contents of this `Accumulator`*/ + final def spliterator: java.util.Spliterator[A] = stepper.spliterator + + /** Produces a sequential Java 8 Stream over the elements of this `Accumulator`*/ + final def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, false) + + /** Produces a parallel Java 8 Stream over the elements of this `Accumulator`*/ + final def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(spliterator, true) + + /** Copies the elements in this `Accumulator` into an `Array` */ + final def toArray(implicit tag: reflect.ClassTag[A]) = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[A](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + a(j) = x(i).asInstanceOf[A] + i += 1 + j += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + a(j) = current(i).asInstanceOf[A] + i += 1 + j += 1 + } + a + } + + /** Copies the elements in this `Accumulator` to a `List` */ + final def toList: List[A] = { + var ans: List[A] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i).asInstanceOf[A] :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i).asInstanceOf[A] :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `Accumulator` to a specified collection. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i).asInstanceOf[A] + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i).asInstanceOf[A] + i += 1 + } + b.result + } +} + +object Accumulator { + private val emptyAnyRefArray = new Array[AnyRef](0) + private val emptyAnyRefArrayArray = new Array[Array[AnyRef]](0) + private val emptyLongArray = new Array[Long](0) + + /** A `Supplier` of `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def supplier[A] = new java.util.function.Supplier[Accumulator[A]]{ def get: Accumulator[A] = new Accumulator[A] } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def adder[A] = new java.util.function.BiConsumer[Accumulator[A], A]{ def accept(ac: Accumulator[A], a: A) { ac += a } } + + /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]) { a1 drain a2 } } +} + +private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) extends AnyStepper[A] { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): AccumulatorStepper[A] = { + val ans = new AccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def next: A = + if (N <= 0) throw new NoSuchElementException("Next in empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i).asInstanceOf[A] + i += 1 + N -= 1 + ans + } + + // Overidden for efficiency + override def tryStep(f: A => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i).asInstanceOf[A]) + i += 1 + N -= 1 + true + } + + // Overidden for efficiency + override def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i).asInstanceOf[A]) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: A => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i).asInstanceOf[A]) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i).asInstanceOf[A]) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): AnyStepper[A] = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } + + override def toString = s"$h $i ${a.mkString("{",",","}")} $n $N" +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala new file mode 100644 index 0000000..8201ac3 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.collectionImpl + +/** An accumulator that works with Java 8 streams; it accepts elements of type `A`, + * is itself an `AC`. Accumulators can handle more than `Int.MaxValue` elements. + */ +trait AccumulatorLike[@specialized(Double, Int, Long) A, AC] { + private[java8] var index: Int = 0 + private[java8] var hIndex: Int = 0 + private[java8] var totalSize: Long = 0L + private[java8] def cumulative(i: Int): Long + + private[java8] def nextBlockSize: Int = { + if (totalSize < 32) 16 + else if (totalSize <= Int.MaxValue) { + val bit = (64 - java.lang.Long.numberOfLeadingZeros(totalSize)) + 1 << (bit - (bit >> 2)) + } + else 1 << 24 + } + + /** Size of the accumulated collection, as a `Long` */ + final def size = totalSize + + /** Remove all accumulated elements from this accumulator. */ + def clear(): Unit = { + index = 0 + hIndex = 0 + totalSize = 0L + } + + private[java8] def seekSlot(ix: Long): Long = { + var lo = -1 + var hi = hIndex + while (lo + 1 < hi) { + val m = (lo + hi) >>> 1 // Shift allows division-as-unsigned, prevents overflow + if (cumulative(m) > ix) hi = m + else lo = m + } + (hi.toLong << 32) | (if (hi==0) ix else (ix - cumulative(hi-1))).toInt + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala new file mode 100644 index 0000000..9703fe9 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -0,0 +1,332 @@ +package scala.compat.java8.collectionImpl + +/** A `DoubleAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class DoubleAccumulator extends AccumulatorLike[Double, DoubleAccumulator] { self => + private[java8] var current: Array[Double] = DoubleAccumulator.emptyDoubleArray + private[java8] var history: Array[Array[Double]] = DoubleAccumulator.emptyDoubleArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1).toLong } + + private def expand(): Unit = { + if (index > 0) { + current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Double](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Double]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `DoubleAccumulator`. */ + final def +=(a: Double): Unit = { + totalSize += 1 + if (index+1 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `DoubleAccumulator`. */ + final def drain(that: DoubleAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 1 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 1>= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 1) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 1) = pv + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 1) = pv + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = DoubleAccumulator.emptyDoubleArray + history = DoubleAccumulator.emptyDoubleArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Double = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Double = apply(i.toLong) + + /** Returns a `DoubleStepper` over the contents of this `DoubleAccumulator`. */ + final def stepper: DoubleStepper = new DoubleAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `DoubleAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfDouble` over the contents of this `DoubleAccumulator`*/ + final def spliterator: java.util.Spliterator.OfDouble = stepper + + /** Produces a sequential Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ + final def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, false) + + /** Produces a parallel Java 8 `DoubleStream` over the elements of this `DoubleAccumulator`*/ + final def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(spliterator, true) + + /** Copies the elements in this `DoubleAccumulator` into an `Array[Double]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Double](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = x(x.length-1).toLong + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `DoubleAccumulator` to a `List` */ + final def toList: List[Double] = { + var ans: List[Double] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `DoubleAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} +object DoubleAccumulator { + private val emptyDoubleArray = new Array[Double](0) + private val emptyDoubleArrayArray = new Array[Array[Double]](0) + + /** A `Supplier` of `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ + def supplier = new java.util.function.Supplier[DoubleAccumulator]{ def get: DoubleAccumulator = new DoubleAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. */ + def adder = new java.util.function.ObjDoubleConsumer[DoubleAccumulator]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Double` to an `DoubleAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[DoubleAccumulator, Double]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + + /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ + def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator) { a1 drain a2 } } +} + +private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator) extends DoubleStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): DoubleAccumulatorStepper = { + val ans = new DoubleAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextDouble: Double = + if (n <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Double => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Double => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.DoubleConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): DoubleStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala new file mode 100644 index 0000000..69a13d1 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -0,0 +1,339 @@ +package scala.compat.java8.collectionImpl + +/** A `IntAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class IntAccumulator extends AccumulatorLike[Int, IntAccumulator] { self => + private[java8] var current: Array[Int] = IntAccumulator.emptyIntArray + private[java8] var history: Array[Array[Int]] = IntAccumulator.emptyIntArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-2).toLong << 32 | (x(x.length-1)&0xFFFFFFFFL) } + + private def expand(): Unit = { + if (index > 0) { + val cuml = (if (hIndex > 0) cumulative(hIndex-1) else 0) + index + current(current.length-2) = (cuml >>> 32).toInt + current(current.length-1) = (cuml & 0xFFFFFFFFL).toInt + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Int](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Int]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `IntAccumulator`. */ + final def +=(a: Int): Unit = { + totalSize += 1 + if (index+2 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `IntAccumulator`. */ + final def drain(that: IntAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 2 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 2 >= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 2) + ans(ans.length - 2) = current(current.length - 2) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 2) = (pv >>> 32).toInt + x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 2) = (pv >>> 32).toInt + x(x.length - 1) = (pv & 0xFFFFFFFFL).toInt + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = IntAccumulator.emptyIntArray + history = IntAccumulator.emptyIntArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Int = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Int = apply(i.toLong) + + /** Returns an `IntStepper` over the contents of this `IntAccumulator` */ + final def stepper: IntStepper = new IntAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `IntAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfInt` over the contents of this `IntAccumulator`*/ + final def spliterator: java.util.Spliterator.OfInt = stepper + + /** Produces a sequential Java 8 `IntStream` over the elements of this `IntAccumulator`*/ + final def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, false) + + /** Produces a parallel Java 8 `IntStream` over the elements of this `IntAccumulator`*/ + final def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(spliterator, true) + + /** Copies the elements in this `IntAccumulator` into an `Array[Int]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Int](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = cumulative(h) + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `IntAccumulator` to a `List` */ + final def toList: List[Int] = { + var ans: List[Int] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `IntAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = cumulative(h) + val n = cuml - pv + pv = cuml + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} + +object IntAccumulator { + private val emptyIntArray = new Array[Int](0) + private val emptyIntArrayArray = new Array[Array[Int]](0) + + /** A `Supplier` of `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ + def supplier = new java.util.function.Supplier[IntAccumulator]{ def get: IntAccumulator = new IntAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.IntStream`'s `collect` method. */ + def adder = new java.util.function.ObjIntConsumer[IntAccumulator]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Int` to an `IntAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[IntAccumulator, Int]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + + /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ + def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator) { a1 drain a2 } } +} + +private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) extends IntStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): IntAccumulatorStepper = { + val ans = new IntAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextInt: Int = + if (N <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Int => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.IntConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Int => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.IntConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): IntStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala new file mode 100644 index 0000000..8cf770c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -0,0 +1,333 @@ +package scala.compat.java8.collectionImpl + +/** A `LongAccumulator` is a low-level collection specialized for gathering + * elements in parallel and then joining them in order by merging them. + * This is a manually specialized variant of `Accumulator` with no actual + * subclassing relationship with `Accumulator`. + */ +final class LongAccumulator extends AccumulatorLike[Long, LongAccumulator] { self => + private[java8] var current: Array[Long] = LongAccumulator.emptyLongArray + private[java8] var history: Array[Array[Long]] = LongAccumulator.emptyLongArrayArray + + private[java8] def cumulative(i: Int) = { val x = history(i); x(x.length-1) } + + private def expand(): Unit = { + if (index > 0) { + current(current.length-1) = (if (hIndex > 0) { val x = history(hIndex-1); x(x.length-1) } else 0) + index + if (hIndex >= history.length) hExpand() + history(hIndex) = current + hIndex += 1 + } + current = new Array[Long](nextBlockSize+1) + index = 0 + } + + private def hExpand(): Unit = { + if (hIndex == 0) history = new Array[Array[Long]](4) + else history = java.util.Arrays.copyOf(history, history.length << 1) + } + + /** Appends an element to this `LongAccumulator`. */ + final def +=(a: Long): Unit = { + totalSize += 1 + if (index+1 >= current.length) expand() + current(index) = a + index += 1 + } + + /** Removes all elements from `that` and appends them to this `LongAccumulator`. */ + final def drain(that: LongAccumulator): Unit = { + var h = 0 + var prev = 0L + var more = true + while (more && h < that.hIndex) { + val cuml = that.cumulative(h) + val n = (cuml - prev).toInt + if (current.length - index - 1 >= n) { + System.arraycopy(that.history(h), 0, current, index, n) + prev = cuml + index += n + h += 1 + } + else more = false + } + if (h >= that.hIndex && current.length - index - 1>= that.index) { + if (that.index > 0) System.arraycopy(that.current, 0, current, index, that.index) + index += that.index + } + else { + val slots = (if (index > 0) 1 else 0) + that.hIndex - h + if (hIndex + slots > history.length) { + val n = math.max(4, 1 << (32 - java.lang.Integer.numberOfLeadingZeros(1 + hIndex + slots))) + history = java.util.Arrays.copyOf(history, n) + } + var pv = (if (hIndex > 0) cumulative(hIndex-1) else 0L) + if (index > 0) { + val x = + if (index < (current.length >>> 3) && current.length - 1 > 32) { + val ans = java.util.Arrays.copyOf(current, index + 1) + ans(ans.length - 1) = current(current.length - 1) + ans + } + else current + pv = pv + index + x(x.length - 1) = pv + history(hIndex) = x + hIndex += 1 + } + while (h < that.hIndex) { + val cuml = that.cumulative(h) + pv = pv + cuml - prev + prev = cuml + val x = that.history(h) + x(x.length - 1) = pv + history(hIndex) = x + h += 1 + hIndex += 1 + } + index = that.index + current = that.current + } + totalSize += that.totalSize + that.clear + } + + override def clear(): Unit = { + super.clear() + current = LongAccumulator.emptyLongArray + history = LongAccumulator.emptyLongArrayArray + } + + /** Retrieves the `ix`th element. */ + final def apply(ix: Long): Long = { + if (totalSize - ix <= index || hIndex == 0) current((ix - (totalSize - index)).toInt) + else { + val w = seekSlot(ix) + history((w >>> 32).toInt)((w & 0xFFFFFFFFL).toInt) + } + } + + /** Retrieves the `ix`th element, using an `Int` index. */ + final def apply(i: Int): Long = apply(i.toLong) + + /** Returns a `LongStepper` over the contents of this `LongAccumulator`. */ + final def stepper: LongStepper = new LongAccumulatorStepper(this) + + /** Returns an `Iterator` over the contents of this `LongAccumulator`. The `Iterator` is not specialized. */ + final def iterator = stepper.iterator + + /** Returns a `java.util.Spliterator.OfLong` over the contents of this `LongAccumulator`*/ + final def spliterator: java.util.Spliterator.OfLong = stepper + + /** Produces a sequential Java 8 `LongStream` over the elements of this `LongAccumulator`*/ + final def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, false) + + /** Produces a parallel Java 8 `LongStream` over the elements of this `LongAccumulator`*/ + final def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(spliterator, true) + + /** Copies the elements in this `LongAccumulator` into an `Array[Long]` */ + final def toArray = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for an array: "+totalSize.toString) + val a = new Array[Long](totalSize.toInt) + var j = 0 + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val cuml = x(x.length-1) + val n = (cuml - pv).toInt + pv = cuml + System.arraycopy(x, 0, a, j, n) + j += n + h += 1 + } + System.arraycopy(current, 0, a, j, index) + j += index + a + } + + /** Copies the elements in this `LongAccumulator` to a `List` */ + final def toList: List[Long] = { + var ans: List[Long] = Nil + var i = index - 1 + while (i >= 0) { + ans = current(i) :: ans + i -= 1 + } + var h = hIndex - 1 + while (h >= 0) { + val a = history(h) + i = (cumulative(h) - (if (h == 0) 0L else cumulative(h-1))).toInt - 1 + while (i >= 0) { + ans = a(i) :: ans + i -= 1 + } + h -= 1 + } + ans + } + + /** Copies the elements in this `LongAccumulator` to a specified collection. + * Note that the target collection is not specialized. + * Usage example: `acc.to[Vector]` + */ + final def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { + if (totalSize > Int.MaxValue) throw new IllegalArgumentException("Too many elements accumulated for a Scala collection: "+totalSize.toString) + val b = cbf() + b.sizeHint(totalSize.toInt) + var h = 0 + var pv = 0L + while (h < hIndex) { + val x = history(h) + val n = cumulative(h) - pv + pv = cumulative(h) + var i = 0 + while (i < n) { + b += x(i) + i += 1 + } + h += 1 + } + var i = 0 + while (i < index) { + b += current(i) + i += 1 + } + b.result + } +} + +object LongAccumulator { + private val emptyLongArray = new Array[Long](0) + private val emptyLongArrayArray = new Array[Array[Long]](0) + + /** A `Supplier` of `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ + def supplier = new java.util.function.Supplier[LongAccumulator]{ def get: LongAccumulator = new LongAccumulator } + + /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.LongStream`'s `collect` method. */ + def adder = new java.util.function.ObjLongConsumer[LongAccumulator]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + + /** A `BiConsumer` that adds a boxed `Long` to an `LongAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ + def boxedAdder = new java.util.function.BiConsumer[LongAccumulator, Long]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + + /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ + def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator) { a1 drain a2 } } +} + +private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) extends LongStepper { + import java.util.Spliterator._ + + private var h = 0 + private var i = 0 + private var a = if (acc.hIndex > 0) acc.history(0) else acc.current + private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index + private var N = acc.totalSize + + private def duplicateSelf(limit: Long = N): LongAccumulatorStepper = { + val ans = new LongAccumulatorStepper(acc) + ans.h = h + ans.i = i + ans.a = a + ans.n = n + ans.N = limit + ans + } + + private def loadMore(): Unit = { + h += 1 + if (h < acc.hIndex) { a = acc.history(h); n = acc.cumulative(h) - acc.cumulative(h-1) } + else { a = acc.current; n = acc.index } + i = 0 + } + + def characteristics = ORDERED | SIZED | SUBSIZED + + def estimateSize = N + + def hasNext = N > 0 + + def nextLong: Long = + if (n <= 0) throw new NoSuchElementException("next on empty Stepper") + else { + if (i >= n) loadMore() + val ans = a(i) + i += 1 + N -= 1 + ans + } + + // Overridden for efficiency + override def tryStep(f: Long => Unit): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def tryAdvance(f: java.util.function.LongConsumer): Boolean = + if (N <= 0) false + else { + if (i >= n) loadMore() + f.accept(a(i)) + i += 1 + N -= 1 + true + } + + // Overridden for efficiency + override def foreach(f: Long => Unit) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + // Overridden for efficiency + override def forEachRemaining(f: java.util.function.LongConsumer) { + while (N > 0) { + if (i >= n) loadMore() + val i0 = i + if ((n-i) > N) n = i + N.toInt + while (i < n) { + f.accept(a(i)) + i += 1 + } + N -= (n - i0) + } + } + + def substep(): LongStepper = + if (N <= 1) null + else { + val half = (N >> 1) + val M = (if (h <= 0) 0L else acc.cumulative(h-1)) + i + val R = M + half + val ans = duplicateSelf(half) + if (h < acc.hIndex) { + val w = acc.seekSlot(R) + h = (w >>> 32).toInt + if (h < acc.hIndex) { + a = acc.history(h) + n = acc.cumulative(h) - (if (h > 0) acc.cumulative(h-1) else 0) + } + else { + a = acc.current + n = acc.index + } + i = (w & 0xFFFFFFFFL).toInt + } + else i += half.toInt + N -= half + ans + } +} diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala new file mode 100644 index 0000000..879b219 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -0,0 +1,145 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StreamConvertersTest { + import java.util.stream._ + import StreamConverters._ + + def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! + def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } + + def arrayO(n: Int) = (1 to n).map(_.toString).toArray + def arrayD(n: Int) = (1 to n).map(_.toDouble).toArray + def arrayI(n: Int) = (1 to n).toArray + def arrayL(n: Int) = (1 to n).map(_.toLong).toArray + + def newStream(n: Int) = java.util.Arrays.stream(arrayO(n)) + def newDoubleStream(n: Int) = java.util.Arrays.stream(arrayD(n)) + def newIntStream(n: Int) = java.util.Arrays.stream(arrayI(n)) + def newLongStream(n: Int) = java.util.Arrays.stream(arrayL(n)) + + val ns = Vector(0, 1, 2, 12, 15, 16, 17, 31, 32, 33, 151, 1298, 7159) + + @Test + def streamAccumulate() { + for (n <- ns) { + val vecO = arrayO(n).toVector + val accO = newStream(n).parallel.accumulate + assertEq(vecO, newStream(n).accumulate.to[Vector], s"stream $n to vector") + assertEq(vecO, accO.to[Vector], s"stream $n to vector in parallel") + assertEq(vecO, accO.toArray.toVector, s"stream $n to vector via array in parallel") + assertEq(vecO, accO.iterator.toVector, s"stream $n to vector via iterator in parallel") + assertEq(vecO, accO.toList.toVector, s"stream $n to vector via list in parallel") + assert((0 until accO.size.toInt).forall(i => vecO(i) == accO(i)), s"stream $n indexed via accumulator") + assert(accO.isInstanceOf[scala.compat.java8.collectionImpl.Accumulator[_]], s"stream $n to generic accumulator") + + for (boxless <- Seq(false, true)) { + val sbox = (if (boxless) "" else "(boxed)") + val vecD = arrayD(n).toVector + val accD = + if (boxless) newDoubleStream(n).parallel.accumulate + else newDoubleStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecD, newDoubleStream(n).accumulate.to[Vector], s"double stream $n to vector $sbox") + assertEq(vecD, accD.to[Vector], s"double stream $n to vector in parallel $sbox") + assertEq(vecD, accD.toArray.toVector, s"double stream $n to vector via array in parallel $sbox") + assertEq(vecD, accD.iterator.toVector, s"double stream $n to vector via iterator in parallel $sbox") + assertEq(vecD, accD.toList.toVector, s"double stream $n to vector via list in parallel $sbox") + assert((0 until accD.size.toInt).forall(i => vecD(i) == accD(i)), s"double stream $n indexed via accumulator $sbox") + assert(accD.isInstanceOf[scala.compat.java8.collectionImpl.DoubleAccumulator], s"double stream $n to generic accumulator $sbox") + + val vecI = arrayI(n).toVector + val accI = + if (boxless) newIntStream(n).parallel.accumulate + else newIntStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecI, newIntStream(n).accumulate.to[Vector], s"int stream $n to vector $sbox") + assertEq(vecI, accI.to[Vector], s"int stream $n to vector in parallel $sbox") + assertEq(vecI, accI.toArray.toVector, s"int stream $n to vector via array in parallel $sbox") + assertEq(vecI, accI.iterator.toVector, s"int stream $n to vector via iterator in parallel $sbox") + assertEq(vecI, accI.toList.toVector, s"int stream $n to vector via list in parallel $sbox") + assert((0 until accI.size.toInt).forall(i => vecI(i) == accI(i)), s"int stream $n indexed via accumulator $sbox") + assert(accI.isInstanceOf[scala.compat.java8.collectionImpl.IntAccumulator], s"int stream $n to generic accumulator $sbox") + + val vecL = arrayL(n).toVector + val accL = + if (boxless) newLongStream(n).parallel.accumulate + else newLongStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecL, newLongStream(n).accumulate.to[Vector], s"long stream $n to vector $sbox") + assertEq(vecL, accL.to[Vector], s"long stream $n to vector in parallel $sbox") + assertEq(vecL, accL.toArray.toVector, s"long stream $n to vector via array in parallel $sbox") + assertEq(vecL, accL.iterator.toVector, s"long stream $n to vector via iterator in parallel $sbox") + assertEq(vecL, accL.toList.toVector, s"long stream $n to vector via list in parallel $sbox") + assert((0 until accL.size.toInt).forall(i => vecL(i) == accL(i)), s"long stream $n indexed via accumulator $sbox") + assert(accL.isInstanceOf[scala.compat.java8.collectionImpl.LongAccumulator], s"long stream $n to generic accumulator $sbox") + } + } + } + + @Test + def streamToScala() { + for (n <- ns) { + val vecO = arrayO(n).toVector + assertEq(vecO, newStream(n).toScala[Vector]) + assertEq(vecO, newStream(n).parallel.toScala[Vector]) + + val vecD = arrayD(n).toVector + assertEq(vecD, newDoubleStream(n).toScala[Vector]) + assertEq(vecD, newDoubleStream(n).parallel.toScala[Vector]) + + val vecI = arrayI(n).toVector + assertEq(vecI, newIntStream(n).toScala[Vector]) + assertEq(vecI, newIntStream(n).parallel.toScala[Vector]) + + val vecL = arrayL(n).toVector + assertEq(vecL, newLongStream(n).toScala[Vector]) + assertEq(vecL, newLongStream(n).parallel.toScala[Vector]) + } + } + + @Test + def streamUnbox() { + assert(newDoubleStream(1).boxed.unboxed.isInstanceOf[DoubleStream]) + assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) + assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) + } + + @Test + def scalaToStream() { + for (n <- ns) { + val arrO = arrayO(n) + val seqO = arrO.toSeq + assertEq(seqO, seqO.seqStream.toScala[Seq]) + assertEq(seqO, seqO.parStream.toScala[Seq]) + assertEq(seqO, arrO.seqStream.toScala[Seq]) + assertEq(seqO, arrO.parStream.toScala[Seq]) + + val arrD = arrayD(n) + val seqD = arrD.toSeq + assertEq(seqD, seqD.seqStream.toScala[Seq]) + assertEq(seqD, seqD.parStream.toScala[Seq]) + assertEq(seqD, arrD.seqStream.toScala[Seq]) + assertEq(seqD, arrD.parStream.toScala[Seq]) + assert(arrD.seqStream.isInstanceOf[DoubleStream]) + assert(arrD.parStream.isInstanceOf[DoubleStream]) + + val arrI = arrayI(n) + val seqI = arrI.toSeq + assertEq(seqI, seqI.seqStream.toScala[Seq]) + assertEq(seqI, seqI.parStream.toScala[Seq]) + assertEq(seqI, arrI.seqStream.toScala[Seq]) + assertEq(seqI, arrI.parStream.toScala[Seq]) + assert(arrI.seqStream.isInstanceOf[IntStream]) + assert(arrI.parStream.isInstanceOf[IntStream]) + + val arrL = arrayL(n) + val seqL = arrL.toSeq + assertEq(seqL, seqL.seqStream.toScala[Seq]) + assertEq(seqL, seqL.parStream.toScala[Seq]) + assertEq(seqL, arrL.seqStream.toScala[Seq]) + assertEq(seqL, arrL.parStream.toScala[Seq]) + assert(arrL.seqStream.isInstanceOf[LongStream]) + assert(arrL.parStream.isInstanceOf[LongStream]) + } + } +} From 302fd15d5b2d4936f8a572bb4eea4b1ac959ff41 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 12:31:13 -0700 Subject: [PATCH 044/340] Pulled out abstractable part of Array steppers for use by any Indexed. --- .../scala/compat/java8/StepConverters.scala | 145 +++++++----------- .../compat/java8/collectionImpl/Stepper.scala | 12 +- .../collectionImpl/StepsLikeIndexed.scala | 19 +++ 3 files changed, 85 insertions(+), 91 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 21b0eeb..4f429ee 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -5,82 +5,65 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ package converterImpls { - import StepConverters.SplitFlags._ - - private[java8] abstract class StepperArrayAny[A, AA, STA >: Null <: StepperArrayAny[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) - extends AnyStepper[A] { - def semiclone(half: Int): STA - def characteristics() = NonNull + Sized + Subsized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): AnyStepper[A] = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } - } - - private[java8] class StepperArrayGenObject[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepperArrayAny[A, Array[A], StepperArrayGenObject[A]](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenObject[A](underlying, i0, half) + import Stepper._ + + private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Array[A], StepsObjectArray[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) } - private[java8] class StepperArrayGenAny[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepperArrayAny[A, Array[A], StepperArrayGenAny[A]](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenAny[A](underlying, i0, half) + private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Array[A], StepsAnyArray[A]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) } - private[java8] class StepperArrayGenUnit(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepperArrayAny[Unit, Array[Unit], StepperArrayGenUnit](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenUnit(underlying, i0, half) + private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Unit, Array[Unit], StepsUnitArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE + def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) } - private[java8] class StepperArrayGenBoolean(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepperArrayAny[Boolean, Array[Boolean], StepperArrayGenBoolean](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenBoolean(underlying, i0, half) + private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Boolean, Array[Boolean], StepsBoxedBooleanArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) } - private[java8] class StepperArrayGenByte(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepperArrayAny[Byte, Array[Byte], StepperArrayGenByte](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenByte(underlying, i0, half) + private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Byte, Array[Byte], StepsBoxedByteArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) } - private[java8] class StepperArrayGenChar(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepperArrayAny[Char, Array[Char], StepperArrayGenChar](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenChar(underlying, i0, half) + private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Char, Array[Char], StepsBoxedCharArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) } - private[java8] class StepperArrayGenShort(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepperArrayAny[Short, Array[Short], StepperArrayGenShort](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenShort(underlying, i0, half) + private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Short, Array[Short], StepsBoxedShortArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) } - private[java8] class StepperArrayGenFloat(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepperArrayAny[Float, Array[Float], StepperArrayGenFloat](underlying, _i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") - def semiclone(half: Int) = new StepperArrayGenFloat(underlying, i0, half) + private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) + extends StepsLikeIndexed[Float, Array[Float], StepsBoxedFloatArray](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } - private[java8] class StepperArrayDouble(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsDoubleArray(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayDouble(underlying, i0, half) + val ans = new StepsDoubleArray(underlying, i0, half) i0 = half ans } @@ -88,15 +71,15 @@ package converterImpls { } } - private[java8] class StepperArrayInt(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsIntArray(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayInt(underlying, i0, half) + val ans = new StepsIntArray(underlying, i0, half) i0 = half ans } @@ -104,15 +87,15 @@ package converterImpls { } } - private[java8] class StepperArrayLong(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { - def characteristics() = NonNull + Sized + Subsized + private[java8] class StepsLongArray(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { + def characteristics() = NonNull + Sized + SubSized def estimateSize() = iN - i0 def hasNext() = i0 < iN - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throw new NoSuchElementException("Empty Stepper") + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def substep() = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 - val ans = new StepperArrayLong(underlying, i0, half) + val ans = new StepsLongArray(underlying, i0, half) i0 = half ans } @@ -121,35 +104,35 @@ package converterImpls { } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepperArrayGenAny[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ - @inline def stepper: AnyStepper[A] = new StepperArrayGenObject[A](underlying, 0, underlying.length) + @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) } final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: AnyStepper[Unit] = new StepperArrayGenUnit(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) } final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: AnyStepper[Boolean] = new StepperArrayGenBoolean(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: AnyStepper[Byte] = new StepperArrayGenByte(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) } final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ - @inline def stepper: AnyStepper[Char] = new StepperArrayGenChar(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) } final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: AnyStepper[Short] = new StepperArrayGenShort(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) } final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ - @inline def stepper: AnyStepper[Float] = new StepperArrayGenFloat(underlying, 0, underlying.length) + @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { @@ -162,7 +145,7 @@ package converterImpls { i0 += java.lang.Character.charCount(cp) cp } - else throw new NoSuchElementException("Empty Stepper") + else throwNSEE } def substep() = { if (iN-3 > i0) { @@ -192,29 +175,19 @@ package converterImpls { } object StepConverters extends converterImpls.Priority2StepConverters { - object SplitFlags { - final val Concurrent = java.util.Spliterator.CONCURRENT - final val Distinct = java.util.Spliterator.DISTINCT - final val Immutable = java.util.Spliterator.IMMUTABLE - final val NonNull = java.util.Spliterator.NONNULL - final val HasOrder = java.util.Spliterator.ORDERED - final val Sized = java.util.Spliterator.SIZED - final val Sorted = java.util.Spliterator.SORTED - final val Subsized = java.util.Spliterator.SUBSIZED - } - import SplitFlags._ import converterImpls._ + import Stepper._ implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepperArrayDouble(underlying, 0, underlying.length) + @inline def stepper: DoubleStepper = new StepsDoubleArray(underlying, 0, underlying.length) } implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepperArrayInt(underlying, 0, underlying.length) + @inline def stepper: IntStepper = new StepsIntArray(underlying, 0, underlying.length) } implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepperArrayLong(underlying, 0, underlying.length) + @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) } implicit class RichStringCanStep(val underlying: String) extends AnyVal { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 3e09ee5..af5c22a 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -181,7 +181,7 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step final def nextStep = { if (!myCacheIsFull) { load() - if (!myCacheIsFull) throw new NoSuchElementException("nextStep in TryStepper") + if (!myCacheIsFull) Stepper.throwNSEE } val ans = myCache myCacheIsFull = false @@ -282,6 +282,8 @@ object Stepper { /** Indicates that a Stepper's children (created with substep()) will all know their size. Steppers that are SubSized must also be Sized. */ val SubSized = Spliterator.SUBSIZED + private[java8] final def throwNSEE: Nothing = throw new NoSuchElementException("Empty Stepper") + private class OfSpliterator[A](sp: Spliterator[A]) extends AnyStepper[A] with java.util.function.Consumer[A] { @@ -312,7 +314,7 @@ object Stepper { } def hasNext = cached || loadCache def next = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cache = null.asInstanceOf[A] cached = false @@ -363,7 +365,7 @@ object Stepper { } def hasNext = cached || loadCache def nextDouble = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans @@ -412,7 +414,7 @@ object Stepper { } def hasNext = cached || loadCache def nextInt = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans @@ -461,7 +463,7 @@ object Stepper { } def hasNext = cached || loadCache def nextLong = { - if (!hasNext) throw new NoSuchElementException("Empty Spliterator in Stepper") + if (!hasNext) throwNSEE val ans = cache cached = false ans diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala new file mode 100644 index 0000000..4b7c1d5 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -0,0 +1,19 @@ +package scala.compat.java8.collectionImpl + +import Stepper._ + +abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) extends AnyStepper[A] { + def semiclone(half: Int): STA + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): AnyStepper[A] = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} From ecf85a38ff278de5ca3f90ee50250e359fe24489 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 12:50:38 -0700 Subject: [PATCH 045/340] Abstracted indexed stepping over Double, Int, Long specialized versions. --- .../scala/compat/java8/StepConverters.scala | 48 ++++-------------- .../collectionImpl/StepsLikeIndexed.scala | 49 +++++++++++++++++++ 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 4f429ee..6385502 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -55,52 +55,22 @@ package converterImpls { def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } - private[java8] class StepsDoubleArray(underlying: Array[Double], var i0: Int, var iN: Int) extends DoubleStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[Array[Double], StepsDoubleArray](underlying, _i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsDoubleArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) } - private[java8] class StepsIntArray(underlying: Array[Int], var i0: Int, var iN: Int) extends IntStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Array[Int], StepsIntArray](underlying, _i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsIntArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) } - private[java8] class StepsLongArray(underlying: Array[Long], var i0: Int, var iN: Int) extends LongStepper { - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN + private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[Array[Long], StepsLongArray](underlying, _i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def substep() = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = new StepsLongArray(underlying, i0, half) - i0 = half - ans - } - else null - } + def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 4b7c1d5..6d82050 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -17,3 +17,52 @@ abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _] else null } } + +abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, var i0: Int, var iN: Int) extends DoubleStepper { + def semiclone(half: Int): STD + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): DoubleStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + + +abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, var i0: Int, var iN: Int) extends IntStepper { + def semiclone(half: Int): STI + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): IntStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + +abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, var i0: Int, var iN: Int) extends LongStepper { + def semiclone(half: Int): STL + def characteristics() = NonNull + Sized + SubSized + def estimateSize() = iN - i0 + def hasNext() = i0 < iN + def substep(): LongStepper = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} From e5624514f0d58f87536ea9adda6e08da315bb071 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 27 Sep 2015 15:03:28 -0700 Subject: [PATCH 046/340] IndexedSeqOptimized added to Stream compat via Stepper. Includes everything through StreamConverters and tests. --- .../scala/compat/java8/StepConverters.scala | 63 +++++++++++++++--- .../scala/compat/java8/StreamConverters.scala | 66 ++++++++++++++----- .../compat/java8/StreamConvertersTest.scala | 24 +++++++ 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 6385502..859c14f 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -72,38 +72,78 @@ package converterImpls { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } + + private[java8] class StepsAnyIndexedSeqOptimized[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, CC, StepsAnyIndexedSeqOptimized[A, CC]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A, CC](underlying, i0, half) + } + + private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[CC, StepsDoubleIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) + } + + private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[CC, StepsIntIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) + } + + private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[CC, StepsLongIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) + } - final class RichArrayAnyCanStep[A](val underlying: Array[A]) extends AnyVal { + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } - final class RichArrayObjectCanStep[A <: Object](val underlying: Array[A]) extends AnyVal{ + final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal{ @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) } - final class RichArrayUnitCanStep(val underlying: Array[Unit]) extends AnyVal{ + final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal{ @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) } - final class RichArrayBooleanCanStep(val underlying: Array[Boolean]) extends AnyVal{ + final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal{ @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } - final class RichArrayByteCanStep(val underlying: Array[Byte]) extends AnyVal{ + final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal{ @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) } - final class RichArrayCharCanStep(val underlying: Array[Char]) extends AnyVal{ + final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal { @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) } - final class RichArrayShortCanStep(val underlying: Array[Short]) extends AnyVal{ + final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal{ @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) } - final class RichArrayFloatCanStep(val underlying: Array[Float]) extends AnyVal{ + final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } + + final class RichIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A, CC](underlying, 0, underlying.length) + } + + final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } + + final class RichIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } + + final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -131,6 +171,7 @@ package converterImpls { trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -141,6 +182,12 @@ package converterImpls { implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + implicit def richDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC) = + new RichIntIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = + new RichLongIndexedSeqOptimizedCanStep[CC](underlying) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 0b9b644..f04e848 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -13,7 +13,7 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority2StreamConverters { +trait Priority3StreamConverters { implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -24,8 +24,27 @@ trait Priority2StreamConverters { def seqStream: Stream[A] = mkAcc().seqStream def parStream: Stream[A] = mkAcc().parStream + } +} + +trait Priority2StreamConverters extends Priority3StreamConverters { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + if (t.isTraversableAgain && t.hasDefiniteSize) { + val sz = t.size + val a = new Array[A](sz) + t.copyToArray(a, 0, sz) + a + } + else t.toArray[A] + } + + def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = + java.util.Arrays.stream(mkArr()) + + def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel } - + implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -44,23 +63,13 @@ trait Priority2StreamConverters { } trait Priority1StreamConverters extends Priority2StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { - private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { - if (t.isTraversableAgain && t.hasDefiniteSize) { - val sz = t.size - val a = new Array[A](sz) - t.copyToArray(a, 0, sz) - a - } - else t.toArray[A] - } - - def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = - java.util.Arrays.stream(mkArr()) - - def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { + private def someStream(parallel: Boolean): Stream[A] = + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) } - + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { def seqStream: Stream[A] = java.util.Arrays.stream(a) def parStream: Stream[A] = seqStream.parallel @@ -122,6 +131,27 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { + implicit class EnrichDoubleIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Double, _]](c: CC) { + private def someStream(parallel: Boolean): DoubleStream = + StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Int, _]](c: CC) { + private def someStream(parallel: Boolean): IntStream = + StreamSupport.intStream(new converterImpls.StepsIntIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Long, _]](c: CC) { + private def someStream(parallel: Boolean): LongStream = + StreamSupport.longStream(new converterImpls.StepsLongIndexedSeqOptimized[CC](c, 0, c.length), parallel) + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 879b219..284f79a 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -103,43 +103,67 @@ class StreamConvertersTest { assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) } + + import collection.mutable.{ArrayBuffer, WrappedArray } + def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } + def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } + def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } + def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } @Test def scalaToStream() { for (n <- ns) { val arrO = arrayO(n) val seqO = arrO.toSeq + val abO = abufO(n) assertEq(seqO, seqO.seqStream.toScala[Seq]) assertEq(seqO, seqO.parStream.toScala[Seq]) assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) + assertEq(seqO, abO.seqStream.toScala[Seq]) + assertEq(seqO, abO.parStream.toScala[Seq]) val arrD = arrayD(n) val seqD = arrD.toSeq + val abD = abufD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) assert(arrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, abD.seqStream.toScala[Seq]) + assertEq(seqD, abD.parStream.toScala[Seq]) + assert(abD.seqStream.isInstanceOf[DoubleStream]) + assert(abD.parStream.isInstanceOf[DoubleStream]) val arrI = arrayI(n) val seqI = arrI.toSeq + val abI = abufI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) assert(arrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, abI.seqStream.toScala[Seq]) + assertEq(seqI, abI.parStream.toScala[Seq]) + assert(abI.seqStream.isInstanceOf[IntStream]) + assert(abI.parStream.isInstanceOf[IntStream]) val arrL = arrayL(n) val seqL = arrL.toSeq + val abL = abufL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) assertEq(seqL, arrL.parStream.toScala[Seq]) assert(arrL.seqStream.isInstanceOf[LongStream]) assert(arrL.parStream.isInstanceOf[LongStream]) + assertEq(seqL, abL.seqStream.toScala[Seq]) + assertEq(seqL, abL.parStream.toScala[Seq]) + assert(abL.seqStream.isInstanceOf[LongStream]) + assert(abL.parStream.isInstanceOf[LongStream]) } } } From 390bbabc8d836f3aacfa45000fb5b50b5c58239a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 30 Sep 2015 14:56:45 -0700 Subject: [PATCH 047/340] FlatHashTable-based collections have steppers and can be converted to streams. --- .../java8/runtime/CollectionInternals.java | 5 ++ .../scala/compat/java8/StepConverters.scala | 58 +++++++++++++- .../scala/compat/java8/StreamConverters.scala | 42 +++++++++- .../collectionImpl/StepsLikeIndexed.scala | 79 +++++++------------ .../compat/java8/StreamConvertersTest.scala | 48 ++++++++++- 5 files changed, 176 insertions(+), 56 deletions(-) create mode 100644 src/main/java/scala/compat/java8/runtime/CollectionInternals.java diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java new file mode 100644 index 0000000..82af37b --- /dev/null +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -0,0 +1,5 @@ +package scala.compat.java8.runtime; + +public class CollectionInternals { + public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } +} diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 859c14f..6b82ac6 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -96,7 +96,31 @@ package converterImpls { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } - + + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) + } + + private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) + } + + private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) + } + + private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -144,6 +168,34 @@ package converterImpls { final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsAnyFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsDoubleFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal { + @inline def stepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsIntFlatHashTable(tbl, 0, tbl.length) + } + } + + final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal { + @inline def stepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable(underlying) + new StepsLongFlatHashTable(tbl, 0, tbl.length) + } + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -172,6 +224,7 @@ package converterImpls { trait Priority3StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) + implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -188,6 +241,9 @@ package converterImpls { new RichIntIndexedSeqOptimizedCanStep[CC](underlying) implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) + implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) + implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index f04e848..435248c 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -63,6 +63,11 @@ trait Priority2StreamConverters extends Priority3StreamConverters { } trait Priority1StreamConverters extends Priority2StreamConverters { + implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { + def seqStream: Stream[A] = java.util.Arrays.stream(a) + def parStream: Stream[A] = seqStream.parallel + } + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { private def someStream(parallel: Boolean): Stream[A] = StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) @@ -70,9 +75,13 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = someStream(true) } - implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { - def seqStream: Stream[A] = java.util.Arrays.stream(a) - def parStream: Stream[A] = seqStream.parallel + implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { + private def someStream(parallel: Boolean): Stream[A] = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.stream(new converterImpls.StepsAnyFlatHashTable[A](tbl, 0, tbl.length), parallel) + } + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) } implicit class RichStream[A](stream: Stream[A]) { @@ -152,6 +161,33 @@ object StreamConverters extends Priority1StreamConverters { def parStream: LongStream = someStream(true) } + implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { + private def someStream(parallel: Boolean): DoubleStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.doubleStream(new converterImpls.StepsDoubleFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Int]) { + private def someStream(parallel: Boolean): IntStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.intStream(new converterImpls.StepsIntFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Long]) { + private def someStream(parallel: Boolean): LongStream = { + val tbl = runtime.CollectionInternals.getTable(fht) + StreamSupport.longStream(new converterImpls.StepsLongFlatHashTable(tbl, 0, tbl.length), parallel) + } + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 6d82050..208af7c 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -1,13 +1,15 @@ package scala.compat.java8.collectionImpl +import java.util.Spliterator import Stepper._ -abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, var i0: Int, var iN: Int) extends AnyStepper[A] { - def semiclone(half: Int): STA - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): AnyStepper[A] = { +/** Abstracts all the generic operations of stepping over an indexable collection */ +abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { + def semiclone(half: Int): Semi + def characteristics(): Int = Ordered + Sized + SubSized + def estimateSize(): Long = iN - i0 + def hasNext(): Boolean = i0 < iN + def substep(): Sub = { if (iN-1 > i0) { val half = (i0+iN) >>> 1 val ans = semiclone(half) @@ -18,51 +20,26 @@ abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _] } } -abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, var i0: Int, var iN: Int) extends DoubleStepper { - def semiclone(half: Int): STD - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): DoubleStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over a generic indexable collection */ +abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) + with AnyStepper[A] +{} +/** Abstracts the operation of stepping over an indexable collection of Doubles */ +abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) + with DoubleStepper +{} -abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, var i0: Int, var iN: Int) extends IntStepper { - def semiclone(half: Int): STI - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): IntStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over an indexable collection of Ints */ +abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) + with IntStepper +{} -abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, var i0: Int, var iN: Int) extends LongStepper { - def semiclone(half: Int): STL - def characteristics() = NonNull + Sized + SubSized - def estimateSize() = iN - i0 - def hasNext() = i0 < iN - def substep(): LongStepper = { - if (iN-1 > i0) { - val half = (i0+iN) >>> 1 - val ans = semiclone(half) - i0 = half - ans - } - else null - } -} +/** Abstracts the operation of stepping over an indexable collection of Longs */ +abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, _i0: Int, _iN: Int) + extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 284f79a..4c4c0ad 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -104,11 +104,20 @@ class StreamConvertersTest { assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) } - import collection.mutable.{ArrayBuffer, WrappedArray } + import collection.mutable.{ ArrayBuffer, WrappedArray } def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } + def wrapO(n: Int): WrappedArray[String] = arrayO(n) + def wrapD(n: Int): WrappedArray[Double] = arrayD(n) + def wrapI(n: Int): WrappedArray[Int] = arrayI(n) + def wrapL(n: Int): WrappedArray[Long] = arrayL(n) + def genhset[A](aa: Array[A]) = { val hs = new collection.mutable.HashSet[A]; aa.foreach(hs += _); hs } + def hsetO(n: Int) = genhset(arrayO(n)) + def hsetD(n: Int) = genhset(arrayD(n)) + def hsetI(n: Int) = genhset(arrayI(n)) + def hsetL(n: Int) = genhset(arrayL(n)) @Test def scalaToStream() { @@ -116,16 +125,25 @@ class StreamConvertersTest { val arrO = arrayO(n) val seqO = arrO.toSeq val abO = abufO(n) + val wrO = wrapO(n) + val hsO = hsetO(n) + // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) assertEq(seqO, seqO.parStream.toScala[Seq]) assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) assertEq(seqO, abO.parStream.toScala[Seq]) + assertEq(seqO, wrO.seqStream.toScala[Seq]) + assertEq(seqO, wrO.parStream.toScala[Seq]) + assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) + assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) val arrD = arrayD(n) val seqD = arrD.toSeq val abD = abufD(n) + val wrD = wrapD(n) + val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) @@ -136,10 +154,20 @@ class StreamConvertersTest { assertEq(seqD, abD.parStream.toScala[Seq]) assert(abD.seqStream.isInstanceOf[DoubleStream]) assert(abD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrD.seqStream.isInstanceOf[DoubleStream]) + assert(wrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) + assertEq(seqD, hsD.parStream.toScala[Seq].sorted) + assert(hsD.seqStream.isInstanceOf[DoubleStream]) + assert(hsD.parStream.isInstanceOf[DoubleStream]) val arrI = arrayI(n) val seqI = arrI.toSeq val abI = abufI(n) + val wrI = wrapI(n) + val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) @@ -150,10 +178,20 @@ class StreamConvertersTest { assertEq(seqI, abI.parStream.toScala[Seq]) assert(abI.seqStream.isInstanceOf[IntStream]) assert(abI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, wrI.seqStream.toScala[Seq]) + assertEq(seqI, wrI.parStream.toScala[Seq]) + assert(wrI.seqStream.isInstanceOf[IntStream]) + assert(wrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) + assertEq(seqI, hsI.parStream.toScala[Seq].sorted) + assert(hsI.seqStream.isInstanceOf[IntStream]) + assert(hsI.parStream.isInstanceOf[IntStream]) val arrL = arrayL(n) val seqL = arrL.toSeq val abL = abufL(n) + val wrL = wrapL(n) + val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) @@ -164,6 +202,14 @@ class StreamConvertersTest { assertEq(seqL, abL.parStream.toScala[Seq]) assert(abL.seqStream.isInstanceOf[LongStream]) assert(abL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrL.seqStream.isInstanceOf[LongStream]) + assert(wrL.parStream.isInstanceOf[LongStream]) + assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) + assertEq(seqL, hsL.parStream.toScala[Seq].sorted) + assert(hsL.seqStream.isInstanceOf[LongStream]) + assert(hsL.parStream.isInstanceOf[LongStream]) } } } From a482301da344b53f643796fe4b05ffa0264ccc71 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 3 Oct 2015 18:30:07 -0700 Subject: [PATCH 048/340] Vector works with Stepper, and if you use the raw Stepper interface it's 10% faster than Iterator. --- .../java8/runtime/CollectionInternals.java | 6 + .../scala/compat/java8/StepConverters.scala | 137 ++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 28 ++++ .../compat/java8/StreamConvertersTest.scala | 24 ++- 4 files changed, 194 insertions(+), 1 deletion(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 82af37b..1f30ea3 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -2,4 +2,10 @@ public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } + public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } + public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } + public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } + public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } + public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } + public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 6b82ac6..e68686e 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -3,6 +3,7 @@ package scala.compat.java8 import language.implicitConversions import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ package converterImpls { import Stepper._ @@ -97,6 +98,125 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } + private[java8] trait StepsVectorLike[A] { + protected def myVector: Vector[A] + protected var index: Int = 32 + protected var data: Array[AnyRef] = null + protected var index1: Int = 32 + protected var data1: Array[AnyRef] = null + protected final def advanceData(iX: Int) { + index1 += 1 + if (index >= 32) initTo(iX) + else { + data = data1(index1).asInstanceOf[Array[AnyRef]] + index = 0 + } + } + protected final def initTo(iX: Int) { + myVector.length match { + case x if x <= 0x20 => + index = iX + data = CollectionInternals.getDisplay0(myVector) + case x if x <= 0x400 => + index1 = iX >>> 5 + data1 = CollectionInternals.getDisplay1(myVector) + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + case x => + var N = 0 + var dataN: Array[AnyRef] = + if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } + else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } + else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } + else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } + while (N > 2) { + dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] + N -= 1 + } + index1 = (iX >>> 5) & 0x1F + data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + } + } + } + + private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, Vector[A], StepsAnyVector[A]](underlying, _i0, _iN) + with StepsVectorLike[A] { + protected def myVector = underlying + def next() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[A] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsAnyVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[Vector[Double], StepsDoubleVector](underlying, _i0, _iN) + with StepsVectorLike[Double] { + protected def myVector = underlying + def nextDouble() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Double] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsDoubleVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Vector[Int], StepsIntVector](underlying, _i0, _iN) + with StepsVectorLike[Int] { + protected def myVector = underlying + def nextInt() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Int] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsIntVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + + private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[Vector[Long], StepsLongVector](underlying, _i0, _iN) + with StepsVectorLike[Long] { + protected def myVector = underlying + def nextLong() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Long] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsLongVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } + } + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } @@ -169,6 +289,10 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) + } + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = { val tbl = runtime.CollectionInternals.getTable(underlying) @@ -244,6 +368,7 @@ package converterImpls { implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) } } @@ -263,6 +388,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) } + implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) + } + + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) + } + + implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) + } + implicit class RichStringCanStep(val underlying: String) extends AnyVal { @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 435248c..80e0da1 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -75,6 +75,13 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = someStream(true) } + implicit class EnrichAnyVectorWithStream[A](c: Vector[A]) { + private def someStream(parallel: Boolean): Stream[A] = + StreamSupport.stream(new converterImpls.StepsAnyVector[A](c, 0, c.length), parallel) + def seqStream: Stream[A] = someStream(false) + def parStream: Stream[A] = someStream(true) + } + implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { private def someStream(parallel: Boolean): Stream[A] = { val tbl = runtime.CollectionInternals.getTable(fht) @@ -161,6 +168,27 @@ object StreamConverters extends Priority1StreamConverters { def parStream: LongStream = someStream(true) } + implicit class EnrichDoubleVectorWithStream(c: Vector[Double]) { + private def someStream(parallel: Boolean): DoubleStream = + StreamSupport.doubleStream(new converterImpls.StepsDoubleVector(c, 0, c.length), parallel) + def seqStream: DoubleStream = someStream(false) + def parStream: DoubleStream = someStream(true) + } + + implicit class EnrichIntVectorWithStream(c: Vector[Int]) { + private def someStream(parallel: Boolean): IntStream = + StreamSupport.intStream(new converterImpls.StepsIntVector(c, 0, c.length), parallel) + def seqStream: IntStream = someStream(false) + def parStream: IntStream = someStream(true) + } + + implicit class EnrichLongVectorWithStream(c: Vector[Long]) { + private def someStream(parallel: Boolean): LongStream = + StreamSupport.longStream(new converterImpls.StepsLongVector(c, 0, c.length), parallel) + def seqStream: LongStream = someStream(false) + def parStream: LongStream = someStream(true) + } + implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { private def someStream(parallel: Boolean): DoubleStream = { val tbl = runtime.CollectionInternals.getTable(fht) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 4c4c0ad..9a5b7f9 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -113,12 +113,16 @@ class StreamConvertersTest { def wrapD(n: Int): WrappedArray[Double] = arrayD(n) def wrapI(n: Int): WrappedArray[Int] = arrayI(n) def wrapL(n: Int): WrappedArray[Long] = arrayL(n) + def vectO(n: Int) = arrayO(n).toVector + def vectD(n: Int) = arrayD(n).toVector + def vectI(n: Int) = arrayI(n).toVector + def vectL(n: Int) = arrayL(n).toVector def genhset[A](aa: Array[A]) = { val hs = new collection.mutable.HashSet[A]; aa.foreach(hs += _); hs } def hsetO(n: Int) = genhset(arrayO(n)) def hsetD(n: Int) = genhset(arrayD(n)) def hsetI(n: Int) = genhset(arrayI(n)) def hsetL(n: Int) = genhset(arrayL(n)) - + @Test def scalaToStream() { for (n <- ns) { @@ -126,6 +130,7 @@ class StreamConvertersTest { val seqO = arrO.toSeq val abO = abufO(n) val wrO = wrapO(n) + val vecO = vectO(n) val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) @@ -136,6 +141,8 @@ class StreamConvertersTest { assertEq(seqO, abO.parStream.toScala[Seq]) assertEq(seqO, wrO.seqStream.toScala[Seq]) assertEq(seqO, wrO.parStream.toScala[Seq]) + assertEq(seqO, vecO.seqStream.toScala[Seq]) + assertEq(seqO, vecO.parStream.toScala[Seq]) assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) @@ -143,6 +150,7 @@ class StreamConvertersTest { val seqD = arrD.toSeq val abD = abufD(n) val wrD = wrapD(n) + val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) assertEq(seqD, seqD.parStream.toScala[Seq]) @@ -158,6 +166,10 @@ class StreamConvertersTest { assertEq(seqD, wrD.parStream.toScala[Seq]) assert(wrD.seqStream.isInstanceOf[DoubleStream]) assert(wrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, vecD.seqStream.toScala[Seq]) + assertEq(seqD, vecD.parStream.toScala[Seq]) + assert(vecD.seqStream.isInstanceOf[DoubleStream]) + assert(vecD.parStream.isInstanceOf[DoubleStream]) assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) assertEq(seqD, hsD.parStream.toScala[Seq].sorted) assert(hsD.seqStream.isInstanceOf[DoubleStream]) @@ -167,6 +179,7 @@ class StreamConvertersTest { val seqI = arrI.toSeq val abI = abufI(n) val wrI = wrapI(n) + val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) assertEq(seqI, seqI.parStream.toScala[Seq]) @@ -182,6 +195,10 @@ class StreamConvertersTest { assertEq(seqI, wrI.parStream.toScala[Seq]) assert(wrI.seqStream.isInstanceOf[IntStream]) assert(wrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, vecI.seqStream.toScala[Seq]) + assertEq(seqI, vecI.parStream.toScala[Seq]) + assert(vecI.seqStream.isInstanceOf[IntStream]) + assert(vecI.parStream.isInstanceOf[IntStream]) assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) assertEq(seqI, hsI.parStream.toScala[Seq].sorted) assert(hsI.seqStream.isInstanceOf[IntStream]) @@ -191,6 +208,7 @@ class StreamConvertersTest { val seqL = arrL.toSeq val abL = abufL(n) val wrL = wrapL(n) + val vecL = vectL(n) val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) assertEq(seqL, seqL.parStream.toScala[Seq]) @@ -206,6 +224,10 @@ class StreamConvertersTest { assertEq(seqD, wrD.parStream.toScala[Seq]) assert(wrL.seqStream.isInstanceOf[LongStream]) assert(wrL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(vecL.seqStream.isInstanceOf[LongStream]) + assert(vecL.parStream.isInstanceOf[LongStream]) assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) assertEq(seqL, hsL.parStream.toScala[Seq].sorted) assert(hsL.seqStream.isInstanceOf[LongStream]) From 4c72bd92afc1fef696a97f05701a8976d9173b46 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 6 Oct 2015 18:26:29 -0700 Subject: [PATCH 049/340] Added a bunch of comprehensiveness tests to StepConvertersTests. (Right now we don't do so well at covering them, though.) --- .../scala/compat/java8/StepConverters.scala | 22 ++- .../compat/java8/StepConvertersTest.scala | 151 ++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 src/test/scala/scala/compat/java8/StepConvertersTest.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index e68686e..8951fc2 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -344,10 +344,28 @@ package converterImpls { else null } } + + final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def stepper: Stepper[A] = { + val acc = new Accumulator[A] + underlying.foreach(acc += _) + acc.stepper + } + } + + trait Priority5StepConverters { + implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) + } + + trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLikeIndexedSeqOptimizedCanStep[A, DD, CC[A, DD] <: collection.IndexedSeqOptimized[A, DD]](underlying: CC[A, DD]) = + new RichIndexedSeqOptimizedCanStep[A, CC[A, DD]](underlying) + } - trait Priority3StepConverters { + trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC) = new RichIndexedSeqOptimizedCanStep[A, CC](underlying) + implicit def richIndexedSeqOptimizedCanStep[A, CC[A] <: collection.IndexedSeqOptimized[A, CC[A]]](underlying: CC[A]) = + new RichIndexedSeqOptimizedCanStep[A, CC[A]](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala new file mode 100644 index 0000000..3df0297 --- /dev/null +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -0,0 +1,151 @@ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StepConvertersTest { + import java.util._ + import collectionImpl._ + import StepConverters._ + import scala.{ collection => co } + import collection.{ mutable => cm, immutable => ci, generic => cg } + + def isAcc[X](x: X) = x match { + case _: AccumulatorStepper[_] => true + case _: DoubleAccumulatorStepper => true + case _: IntAccumulatorStepper => true + case _: LongAccumulatorStepper => true + case _ => false + } + + def _eh_[X](x: => X) { IFFY(x) } + + def IFFY[X](x: => X) { + assert(x.isInstanceOf[Stepper[_]]) + assert(isAcc(x)) + } + + def good[X](x: => X) { + assert(x.isInstanceOf[Stepper[_]]) + assert(!isAcc(x)) + } + + @Test + def comprehensivelyGeneric() { + // Collection section + IFFY( co.Iterator[String]("salmon").buffered.stepper ) + IFFY( co.IndexedSeq[String]("salmon").stepper ) + IFFY( co.Iterable[String]("salmon").stepper ) + IFFY( co.Iterable[String]("salmon").view.stepper ) + IFFY( co.Iterator[String]("salmon").stepper ) + IFFY( co.LinearSeq[String]("salmon").stepper ) + IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( co.Seq[String]("salmon").stepper ) + IFFY( co.Seq[String]("salmon").view.stepper ) + IFFY( co.Set[String]("salmon").stepper ) + IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + IFFY( co.SortedSet[String]("salmon").stepper ) + IFFY( co.Traversable[String]("salmon").stepper ) + IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) + IFFY( co.Traversable[String]("salmon").view.stepper ) + + // Generic section + + // Immutable section + IFFY( ci.::("salmon", Nil).stepper ) + IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.HashSet[String]("salmon").stepper ) + IFFY( ci.IndexedSeq[String]("salmon").stepper ) + IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + IFFY( ci.Iterable[String]("salmon").stepper ) + IFFY( ci.LinearSeq[String]("salmon").stepper ) + IFFY( ci.List[String]("salmon").stepper ) + IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.ListSet[String]("salmon").stepper ) + IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.Queue[String]("salmon").stepper ) + IFFY( ci.Seq[String]("salmon").stepper ) + IFFY( ci.Set[String]("salmon").stepper ) + IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.SortedSet[String]("salmon").stepper ) + IFFY( ci.Stack[String]("salmon").stepper ) + IFFY( ci.Stream[String]("salmon").stepper ) + IFFY( ci.Stream[String]("salmon").view.stepper ) + IFFY( ci.Traversable[String]("salmon").stepper ) + IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.TreeSet[String]("salmon").stepper ) + good( ci.Vector[String]("salmon").stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) + IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) + IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) + IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) + IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + good( cm.ArrayBuffer[String]("salmon").stepper ) + good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) + good( (Array("salmon"): cm.ArrayOps[String]).stepper ) + good( cm.ArraySeq[String]("salmon").stepper ) + _eh_( cm.ArrayStack[String]("salmon").stepper ) + IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) + IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashSet[String]("salmon").stepper ) + IFFY( cm.IndexedSeq[String]("salmon").stepper ) + IFFY( cm.IndexedSeq[String]("salmon").view.stepper ) + IFFY( cm.Iterable[String]("salmon").stepper ) + IFFY( cm.LinearSeq[String]("salmon").stepper ) + IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.LinkedHashSet[String]("salmon").stepper ) + IFFY( cm.ListBuffer[String]("salmon").stepper ) + IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.MutableList[String]("salmon").stepper ) + IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + IFFY( cm.PriorityQueue[String]("salmon").stepper ) + IFFY( cm.Queue[String]("salmon").stepper ) + good( cm.ResizableArray[String]("salmon").stepper ) + IFFY( cm.Seq[String]("salmon").stepper ) + IFFY( cm.Set[String]("salmon").stepper ) + IFFY( cm.SortedSet[String]("salmon").stepper ) + IFFY( cm.Stack[String]("salmon").stepper ) + IFFY( cm.Traversable[String]("salmon").stepper ) + IFFY( cm.TreeSet[String]("salmon").stepper ) + IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) + IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + good( (Array("salmon"): cm.WrappedArray[String]).stepper ) + + // Java 6 converters section + + // Concurrent section + } + + @Test + def comprehensivelyDouble() { + } + + @Test + def comprehensivelyInt() { + // Int-specific tests + IFFY( co.BitSet(42).stepper ) + IFFY( ci.BitSet(42).stepper ) + IFFY( cm.BitSet(42).stepper ) + IFFY( (1 until 2).stepper ) + } + + @Test + def comprehensivelyLong() { + // Long-specific tests + IFFY( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + } + + @Test + def comprehensivelySpecific() { + IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) + good( ("salmon": ci.StringOps).stepper ) + good( ("salmon": ci.WrappedString).stepper ) + } +} From 40c0117cf4be435016b59357ff5162d8c8857616 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 6 Oct 2015 20:53:07 -0700 Subject: [PATCH 050/340] Ranges step quickly. Nearly complete coverage testing for generics. --- .../scala/compat/java8/StepConverters.scala | 43 ++++++++++++++++++- .../compat/java8/StepConvertersTest.scala | 13 +++--- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 8951fc2..56373f6 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -98,6 +98,30 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[Range, StepsIntRange](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) + } + + private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) + extends StepsLikeIndexed[T, collection.immutable.NumericRange[T], StepsAnyNumericRange[T]](underlying, _i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) + } + + private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[collection.immutable.NumericRange[Int], StepsIntNumericRange](underlying, _i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) + } + + private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[collection.immutable.NumericRange[Long], StepsLongNumericRange](underlying, _i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) + } + private[java8] trait StepsVectorLike[A] { protected def myVector: Vector[A] protected var index: Int = 32 @@ -289,6 +313,10 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { + @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) + } + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) } @@ -383,10 +411,11 @@ package converterImpls { new RichIntIndexedSeqOptimizedCanStep[CC](underlying) implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) - implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) } } @@ -410,6 +439,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) } + implicit final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) + } + + implicit final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) + } + + implicit final class RichRangeCanStep(private val underlying: Range) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) + } + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 3df0297..9d7d66a 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -8,7 +8,7 @@ class StepConvertersTest { import collectionImpl._ import StepConverters._ import scala.{ collection => co } - import collection.{ mutable => cm, immutable => ci, generic => cg } + import collection.{ mutable => cm, immutable => ci, concurrent => cc } def isAcc[X](x: X) = x match { case _: AccumulatorStepper[_] => true @@ -49,8 +49,6 @@ class StepConvertersTest { IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) IFFY( co.Traversable[String]("salmon").view.stepper ) - // Generic section - // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) @@ -121,10 +119,13 @@ class StepConvertersTest { // Java 6 converters section // Concurrent section + IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) } @Test def comprehensivelyDouble() { + //Double-specific tests } @Test @@ -132,18 +133,20 @@ class StepConvertersTest { // Int-specific tests IFFY( co.BitSet(42).stepper ) IFFY( ci.BitSet(42).stepper ) + good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) - IFFY( (1 until 2).stepper ) + good( (1 until 2).stepper ) } @Test def comprehensivelyLong() { // Long-specific tests - IFFY( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) } @Test def comprehensivelySpecific() { + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) From 4013be65f1233404adfc3311583dec4536c47954 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 17:52:53 -0700 Subject: [PATCH 051/340] Filled in all the stepper tests and simplifed IndexedSeqOptimized dispatching. --- .../scala/compat/java8/StepConverters.scala | 45 ++- .../scala/compat/java8/StreamConverters.scala | 4 +- .../compat/java8/StepConvertersTest.scala | 302 +++++++++++++++++- 3 files changed, 334 insertions(+), 17 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 56373f6..767d218 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -74,10 +74,10 @@ package converterImpls { def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } - private[java8] class StepsAnyIndexedSeqOptimized[A, CC <: collection.IndexedSeqOptimized[A, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, CC, StepsAnyIndexedSeqOptimized[A, CC]](underlying, _i0, _iN) { + private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, collection.IndexedSeqOptimized[A, _], StepsAnyIndexedSeqOptimized[A]](underlying, _i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A, CC](underlying, i0, half) + def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) } private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) @@ -297,8 +297,8 @@ package converterImpls { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqOptimizedCanStep[A, CC <: collection.IndexedSeqOptimized[A, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A, CC](underlying, 0, underlying.length) + final class RichIndexedSeqOptimizedCanStep[A](private val underlying: collection.IndexedSeqOptimized[A, _]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A](underlying, 0, underlying.length) } final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { @@ -374,26 +374,51 @@ package converterImpls { } final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def stepper: Stepper[A] = { + def stepper: AnyStepper[A] = { val acc = new Accumulator[A] underlying.foreach(acc += _) acc.stepper } } + final class RichDoubleTraversableOnceCanStep(private val underlying: TraversableOnce[Double]) extends AnyVal { + def stepper: DoubleStepper = { + val acc = new DoubleAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + + final class RichIntTraversableOnceCanStep(private val underlying: TraversableOnce[Int]) extends AnyVal { + def stepper: IntStepper = { + val acc = new IntAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + + final class RichLongTraversableOnceCanStep(private val underlying: TraversableOnce[Long]) extends AnyVal { + def stepper: LongStepper = { + val acc = new LongAccumulator + underlying.foreach(acc += _) + acc.stepper + } + } + trait Priority5StepConverters { implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) } trait Priority4StepConverters extends Priority5StepConverters { - implicit def richLikeIndexedSeqOptimizedCanStep[A, DD, CC[A, DD] <: collection.IndexedSeqOptimized[A, DD]](underlying: CC[A, DD]) = - new RichIndexedSeqOptimizedCanStep[A, CC[A, DD]](underlying) + implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) + implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) + implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) } trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A, CC[A] <: collection.IndexedSeqOptimized[A, CC[A]]](underlying: CC[A]) = - new RichIndexedSeqOptimizedCanStep[A, CC[A]](underlying) + implicit def richIndexedSeqOptimizedCanStep[A](underlying: collection.IndexedSeqOptimized[A, _]) = + new RichIndexedSeqOptimizedCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 80e0da1..6a21437 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -68,9 +68,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = seqStream.parallel } - implicit class EnrichGenericIndexedSeqOptimizedWithStream[A, CC <: collection.IndexedSeqOptimized[A, _]](c: CC) { + implicit class EnrichGenericIndexedSeqOptimizedWithStream[A](c: collection.IndexedSeqOptimized[A, _]) { private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A, CC](c, 0, c.length), parallel) + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A](c, 0, c.length), parallel) def seqStream: Stream[A] = someStream(false) def parStream: Stream[A] = someStream(true) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 9d7d66a..eb65c97 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -18,20 +18,35 @@ class StepConvertersTest { case _ => false } - def _eh_[X](x: => X) { IFFY(x) } + trait SpecCheck { def apply[X](x: X): Boolean } + object SpecCheck { + def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } + } + + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { IFFY(x)(correctSpec) } - def IFFY[X](x: => X) { + def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) assert(isAcc(x)) } - def good[X](x: => X) { + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) assert(!isAcc(x)) } + def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { + println(x.getClass.getName + " -> " + isAcc(x)) + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + } + @Test def comprehensivelyGeneric() { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + // Collection section IFFY( co.Iterator[String]("salmon").buffered.stepper ) IFFY( co.IndexedSeq[String]("salmon").stepper ) @@ -92,7 +107,7 @@ class StepConvertersTest { IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashSet[String]("salmon").stepper ) IFFY( cm.IndexedSeq[String]("salmon").stepper ) - IFFY( cm.IndexedSeq[String]("salmon").view.stepper ) + good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) IFFY( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) @@ -125,27 +140,304 @@ class StepConvertersTest { @Test def comprehensivelyDouble() { + implicit val spec = SpecCheck(_.isInstanceOf[DoubleStepper]) //Double-specific tests + + // Collection section + IFFY( co.Iterator[Double](3.14159).buffered.stepper ) + IFFY( co.IndexedSeq[Double](3.14159).stepper ) + IFFY( co.Iterable[Double](3.14159).stepper ) + IFFY( co.Iterable[Double](3.14159).view.stepper ) + IFFY( co.Iterator[Double](3.14159).stepper ) + IFFY( co.LinearSeq[Double](3.14159).stepper ) + //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( co.Seq[Double](3.14159).stepper ) + IFFY( co.Seq[Double](3.14159).view.stepper ) + IFFY( co.Set[Double](3.14159).stepper ) + //IFFY( co.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( co.SortedSet[Double](3.14159).stepper ) + IFFY( co.Traversable[Double](3.14159).stepper ) + IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) + IFFY( co.Traversable[Double](3.14159).view.stepper ) + + // Immutable section + IFFY( ci.::(3.14159, Nil).stepper ) + //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) + //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.HashSet[Double](3.14159).stepper ) + IFFY( ci.IndexedSeq[Double](3.14159).stepper ) + //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) + IFFY( ci.Iterable[Double](3.14159).stepper ) + IFFY( ci.LinearSeq[Double](3.14159).stepper ) + IFFY( ci.List[Double](3.14159).stepper ) + //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.ListSet[Double](3.14159).stepper ) + //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) + //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.Queue[Double](3.14159).stepper ) + IFFY( ci.Seq[Double](3.14159).stepper ) + IFFY( ci.Set[Double](3.14159).stepper ) + //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.SortedSet[Double](3.14159).stepper ) + IFFY( ci.Stack[Double](3.14159).stepper ) + IFFY( ci.Stream[Double](3.14159).stepper ) + IFFY( ci.Stream[Double](3.14159).view.stepper ) + IFFY( ci.Traversable[Double](3.14159).stepper ) + //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( ci.TreeSet[Double](3.14159).stepper ) + good( ci.Vector[Double](3.14159).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) + IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) + //IFFY( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).stepper ) + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) + IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) + //IFFY( cm.AnyRefMap[Double,Double](2.718281828 -> 3.14159).stepper ) + good( cm.ArrayBuffer[Double](3.14159).stepper ) + good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) + good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) + good( cm.ArraySeq[Double](3.14159).stepper ) + _eh_( cm.ArrayStack[Double](3.14159).stepper ) + IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) + //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.HashSet[Double](3.14159).stepper ) + IFFY( cm.IndexedSeq[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).view.stepper ) + IFFY( cm.Iterable[Double](3.14159).stepper ) + IFFY( cm.LinearSeq[Double](3.14159).stepper ) + //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) + IFFY( cm.ListBuffer[Double](3.14159).stepper ) + //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) + //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.MutableList[Double](3.14159).stepper ) + //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + IFFY( cm.PriorityQueue[Double](3.14159).stepper ) + IFFY( cm.Queue[Double](3.14159).stepper ) + good( cm.ResizableArray[Double](3.14159).stepper ) + IFFY( cm.Seq[Double](3.14159).stepper ) + IFFY( cm.Set[Double](3.14159).stepper ) + IFFY( cm.SortedSet[Double](3.14159).stepper ) + IFFY( cm.Stack[Double](3.14159).stepper ) + IFFY( cm.Traversable[Double](3.14159).stepper ) + IFFY( cm.TreeSet[Double](3.14159).stepper ) + IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) + //IFFY( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).stepper ) + //IFFY( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).stepper ) } @Test def comprehensivelyInt() { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + // Int-specific tests IFFY( co.BitSet(42).stepper ) IFFY( ci.BitSet(42).stepper ) good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) + + // Collection section + IFFY( co.Iterator[Int](654321).buffered.stepper ) + IFFY( co.IndexedSeq[Int](654321).stepper ) + IFFY( co.Iterable[Int](654321).stepper ) + IFFY( co.Iterable[Int](654321).view.stepper ) + IFFY( co.Iterator[Int](654321).stepper ) + IFFY( co.LinearSeq[Int](654321).stepper ) + //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( co.Seq[Int](654321).stepper ) + IFFY( co.Seq[Int](654321).view.stepper ) + IFFY( co.Set[Int](654321).stepper ) + //IFFY( co.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( co.SortedSet[Int](654321).stepper ) + IFFY( co.Traversable[Int](654321).stepper ) + IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) + IFFY( co.Traversable[Int](654321).view.stepper ) + + // Immutable section + IFFY( ci.::(654321, Nil).stepper ) + //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) + //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.HashSet[Int](654321).stepper ) + IFFY( ci.IndexedSeq[Int](654321).stepper ) + //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) + IFFY( ci.Iterable[Int](654321).stepper ) + IFFY( ci.LinearSeq[Int](654321).stepper ) + IFFY( ci.List[Int](654321).stepper ) + //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.ListSet[Int](654321).stepper ) + //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) + //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.Queue[Int](654321).stepper ) + IFFY( ci.Seq[Int](654321).stepper ) + IFFY( ci.Set[Int](654321).stepper ) + //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.SortedSet[Int](654321).stepper ) + IFFY( ci.Stack[Int](654321).stepper ) + IFFY( ci.Stream[Int](654321).stepper ) + IFFY( ci.Stream[Int](654321).view.stepper ) + IFFY( ci.Traversable[Int](654321).stepper ) + //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( ci.TreeSet[Int](654321).stepper ) + good( ci.Vector[Int](654321).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) + IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) + //IFFY( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).stepper ) + IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) + IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) + //IFFY( cm.AnyRefMap[Int,Int](0xDEEDED -> 654321).stepper ) + good( cm.ArrayBuffer[Int](654321).stepper ) + good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) + good( (Array(654321): cm.ArrayOps[Int]).stepper ) + good( cm.ArraySeq[Int](654321).stepper ) + _eh_( cm.ArrayStack[Int](654321).stepper ) + IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) + //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.HashSet[Int](654321).stepper ) + IFFY( cm.IndexedSeq[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).view.stepper ) + IFFY( cm.Iterable[Int](654321).stepper ) + IFFY( cm.LinearSeq[Int](654321).stepper ) + //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.LinkedHashSet[Int](654321).stepper ) + IFFY( cm.ListBuffer[Int](654321).stepper ) + //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) + //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.MutableList[Int](654321).stepper ) + //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + IFFY( cm.PriorityQueue[Int](654321).stepper ) + IFFY( cm.Queue[Int](654321).stepper ) + good( cm.ResizableArray[Int](654321).stepper ) + IFFY( cm.Seq[Int](654321).stepper ) + IFFY( cm.Set[Int](654321).stepper ) + IFFY( cm.SortedSet[Int](654321).stepper ) + IFFY( cm.Stack[Int](654321).stepper ) + IFFY( cm.Traversable[Int](654321).stepper ) + IFFY( cm.TreeSet[Int](654321).stepper ) + IFFY( cm.UnrolledBuffer[Int](654321).stepper ) + //IFFY( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( (Array(654321): cm.WrappedArray[Int]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Int, Int](0xDEEDED -> 654321).stepper ) + //IFFY( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).stepper ) } @Test def comprehensivelyLong() { + implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) + // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) - } + + // Collection section + IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) + IFFY( co.IndexedSeq[Long](0x123456789L).stepper ) + IFFY( co.Iterable[Long](0x123456789L).stepper ) + IFFY( co.Iterable[Long](0x123456789L).view.stepper ) + IFFY( co.Iterator[Long](0x123456789L).stepper ) + IFFY( co.LinearSeq[Long](0x123456789L).stepper ) + //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( co.Seq[Long](0x123456789L).stepper ) + IFFY( co.Seq[Long](0x123456789L).view.stepper ) + IFFY( co.Set[Long](0x123456789L).stepper ) + //IFFY( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( co.SortedSet[Long](0x123456789L).stepper ) + IFFY( co.Traversable[Long](0x123456789L).stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) + IFFY( co.Traversable[Long](0x123456789L).view.stepper ) + + // Immutable section + IFFY( ci.::(0x123456789L, Nil).stepper ) + //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) + //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.HashSet[Long](0x123456789L).stepper ) + IFFY( ci.IndexedSeq[Long](0x123456789L).stepper ) + //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) + IFFY( ci.Iterable[Long](0x123456789L).stepper ) + IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) + IFFY( ci.List[Long](0x123456789L).stepper ) + //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.ListSet[Long](0x123456789L).stepper ) + //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) + //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.Queue[Long](0x123456789L).stepper ) + IFFY( ci.Seq[Long](0x123456789L).stepper ) + IFFY( ci.Set[Long](0x123456789L).stepper ) + //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.SortedSet[Long](0x123456789L).stepper ) + IFFY( ci.Stack[Long](0x123456789L).stepper ) + IFFY( ci.Stream[Long](0x123456789L).stepper ) + IFFY( ci.Stream[Long](0x123456789L).view.stepper ) + IFFY( ci.Traversable[Long](0x123456789L).stepper ) + //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( ci.TreeSet[Long](0x123456789L).stepper ) + good( ci.Vector[Long](0x123456789L).stepper ) + + // Mutable section + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) + IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) + //IFFY( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).stepper ) + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) + IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) + //IFFY( cm.AnyRefMap[Long,Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.ArrayBuffer[Long](0x123456789L).stepper ) + good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) + good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) + good( cm.ArraySeq[Long](0x123456789L).stepper ) + _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) + IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) + //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.HashSet[Long](0x123456789L).stepper ) + IFFY( cm.IndexedSeq[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) + IFFY( cm.Iterable[Long](0x123456789L).stepper ) + IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) + //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) + IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) + //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) + //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.MutableList[Long](0x123456789L).stepper ) + //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) + IFFY( cm.Queue[Long](0x123456789L).stepper ) + good( cm.ResizableArray[Long](0x123456789L).stepper ) + IFFY( cm.Seq[Long](0x123456789L).stepper ) + IFFY( cm.Set[Long](0x123456789L).stepper ) + IFFY( cm.SortedSet[Long](0x123456789L).stepper ) + IFFY( cm.Stack[Long](0x123456789L).stepper ) + IFFY( cm.Traversable[Long](0x123456789L).stepper ) + IFFY( cm.TreeSet[Long](0x123456789L).stepper ) + IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) + //IFFY( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) + + // Java 6 converters section + + // Concurrent section + //IFFY( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + //IFFY( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).stepper ) + } @Test def comprehensivelySpecific() { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) From e4c18a3a5c3ee4bca8a7b8e9f3140c9cffd1f671 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 20:25:26 -0700 Subject: [PATCH 052/340] Simplified StepsLikeIndexed implementation. --- .../scala/compat/java8/StepConverters.scala | 46 +++++++++---------- .../collectionImpl/StepsLikeIndexed.scala | 8 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 767d218..531561b 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -9,115 +9,115 @@ package converterImpls { import Stepper._ private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Array[A], StepsObjectArray[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) } private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Array[A], StepsAnyArray[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) } private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Unit, Array[Unit], StepsUnitArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) } private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Boolean, Array[Boolean], StepsBoxedBooleanArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) } private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Byte, Array[Byte], StepsBoxedByteArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) } private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Char, Array[Char], StepsBoxedCharArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) } private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Short, Array[Short], StepsBoxedShortArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) } private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Float, Array[Float], StepsBoxedFloatArray](underlying, _i0, _iN) { + extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) } private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[Array[Double], StepsDoubleArray](underlying, _i0, _iN) { + extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) } private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Array[Int], StepsIntArray](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) } private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[Array[Long], StepsLongArray](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, collection.IndexedSeqOptimized[A, _], StepsAnyIndexedSeqOptimized[A]](underlying, _i0, _iN) { + extends StepsLikeIndexed[A, StepsAnyIndexedSeqOptimized[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) } private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[CC, StepsDoubleIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeqOptimized[CC]](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[CC, StepsIntIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntIndexedSeqOptimized[CC]](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[CC, StepsLongIndexedSeqOptimized[CC]](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongIndexedSeqOptimized[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) } private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Range, StepsIntRange](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) } private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) - extends StepsLikeIndexed[T, collection.immutable.NumericRange[T], StepsAnyNumericRange[T]](underlying, _i0, _iN) { + extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) } private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[collection.immutable.NumericRange[Int], StepsIntNumericRange](underlying, _i0, _iN) { + extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) } private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[collection.immutable.NumericRange[Long], StepsLongNumericRange](underlying, _i0, _iN) { + extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) } @@ -166,7 +166,7 @@ package converterImpls { } private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, Vector[A], StepsAnyVector[A]](underlying, _i0, _iN) + extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) with StepsVectorLike[A] { protected def myVector = underlying def next() = if (hasNext()) { @@ -185,7 +185,7 @@ package converterImpls { } private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[Vector[Double], StepsDoubleVector](underlying, _i0, _iN) + extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) with StepsVectorLike[Double] { protected def myVector = underlying def nextDouble() = if (hasNext()) { @@ -204,7 +204,7 @@ package converterImpls { } private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[Vector[Int], StepsIntVector](underlying, _i0, _iN) + extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) with StepsVectorLike[Int] { protected def myVector = underlying def nextInt() = if (hasNext()) { @@ -223,7 +223,7 @@ package converterImpls { } private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[Vector[Long], StepsLongVector](underlying, _i0, _iN) + extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) with StepsVectorLike[Long] { protected def myVector = underlying def nextLong() = if (hasNext()) { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index 208af7c..b9dfa55 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -21,25 +21,25 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsLikeIndexed[A, AA, STA >: Null <: StepsLikeIndexed[A, AA, _]](underlying: AA, _i0: Int, _iN: Int) +abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleLikeIndexed[DD, STD >: Null <: StepsDoubleLikeIndexed[DD, _]](underlying: DD, _i0: Int, _iN: Int) +abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntLikeIndexed[II, STI >: Null <: StepsIntLikeIndexed[II, _]](underlying: II, _i0: Int, _iN: Int) +abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongLikeIndexed[LL, STL >: Null <: StepsLongLikeIndexed[LL, _]](underlying: LL, _i0: Int, _iN: Int) +abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper {} From 27e72aa9f6f44bd55aedcc3f1ec041899b9f7c77 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 7 Oct 2015 20:46:14 -0700 Subject: [PATCH 053/340] Added missing file! Also covered all of IndexedSeqLike. Note that almost all of IndexedSeqLike is Optimized (or should be) or I already have a workaround (e.g. Vector). --- .../scala/compat/java8/StepConverters.scala | 56 ++++++++-------- .../scala/compat/java8/StreamConverters.scala | 16 ++--- .../collectionImpl/StepsLikeGapped.scala | 66 +++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 31 +++++---- 4 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 531561b..ea7093b 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -74,28 +74,28 @@ package converterImpls { def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } - private[java8] class StepsAnyIndexedSeqOptimized[A](underlying: collection.IndexedSeqOptimized[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyIndexedSeqOptimized[A]](_i0, _iN) { + private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) + extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeqOptimized[A](underlying, i0, half) + def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) } - private[java8] class StepsDoubleIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) } - private[java8] class StepsIntIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) } - private[java8] class StepsLongIndexedSeqOptimized[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongIndexedSeqOptimized[CC]](_i0, _iN) { + private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) + extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongIndexedSeqOptimized[CC](underlying, i0, half) + def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) @@ -297,20 +297,20 @@ package converterImpls { @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqOptimizedCanStep[A](private val underlying: collection.IndexedSeqOptimized[A, _]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeqOptimized[A](underlying, 0, underlying.length) + final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) } - final class RichDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongIndexedSeqOptimized[CC](underlying, 0, underlying.length) + final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @@ -417,8 +417,8 @@ package converterImpls { trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqOptimizedCanStep[A](underlying: collection.IndexedSeqOptimized[A, _]) = - new RichIndexedSeqOptimizedCanStep[A](underlying) + implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = + new RichIndexedSeqCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) } @@ -430,12 +430,12 @@ package converterImpls { implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) - implicit def richDoubleIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Double, _]](underlying: CC) = - new RichDoubleIndexedSeqOptimizedCanStep[CC](underlying) - implicit def richIntIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Int, _]](underlying: CC) = - new RichIntIndexedSeqOptimizedCanStep[CC](underlying) - implicit def richLongIndexedSeqOptimizedCanStep[CC <: collection.IndexedSeqOptimized[Long, _]](underlying: CC) = - new RichLongIndexedSeqOptimizedCanStep[CC](underlying) + implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqCanStep[CC](underlying) + implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = + new RichIntIndexedSeqCanStep[CC](underlying) + implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = + new RichLongIndexedSeqCanStep[CC](underlying) implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 6a21437..d45a205 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -68,9 +68,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { def parStream: Stream[A] = seqStream.parallel } - implicit class EnrichGenericIndexedSeqOptimizedWithStream[A](c: collection.IndexedSeqOptimized[A, _]) { + implicit class EnrichGenericIndexedSeqWithStream[A](c: collection.IndexedSeqLike[A, _]) { private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeqOptimized[A](c, 0, c.length), parallel) + StreamSupport.stream(new converterImpls.StepsAnyIndexedSeq[A](c, 0, c.length), parallel) def seqStream: Stream[A] = someStream(false) def parStream: Stream[A] = someStream(true) } @@ -147,23 +147,23 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { - implicit class EnrichDoubleIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Double, _]](c: CC) { + implicit class EnrichDoubleIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Double, _]](c: CC) { private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: DoubleStream = someStream(false) def parStream: DoubleStream = someStream(true) } - implicit class EnrichIntIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Int, _]](c: CC) { + implicit class EnrichIntIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Int, _]](c: CC) { private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.intStream(new converterImpls.StepsIntIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: IntStream = someStream(false) def parStream: IntStream = someStream(true) } - implicit class EnrichLongIndexedSeqOptimizedWithStream[CC <: collection.IndexedSeqOptimized[Long, _]](c: CC) { + implicit class EnrichLongIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Long, _]](c: CC) { private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongIndexedSeqOptimized[CC](c, 0, c.length), parallel) + StreamSupport.longStream(new converterImpls.StepsLongIndexedSeq[CC](c, 0, c.length), parallel) def seqStream: LongStream = someStream(false) def parStream: LongStream = someStream(true) } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala new file mode 100644 index 0000000..87bb295 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala @@ -0,0 +1,66 @@ +package scala.compat.java8.collectionImpl + +import annotation.tailrec + +import Stepper._ + +/** Abstracts all the generic operations of stepping over a backing array + * for some collection where the elements are stored generically and some + * may be missing. Subclasses should set `currentEntry` to `null` when it + * is used as a signal to look for more entries in the array. (This also + * allows a subclass to traverse a sublist by updating `currentEntry`.) + */ +abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { + protected var currentEntry: AnyRef = null + def semiclone(half: Int): Semi + def characteristics(): Int = Ordered + def estimateSize(): Long = if (!hasNext) 0 else iN - i0 + def hasNext(): Boolean = currentEntry != null || (i0 < iN && { + do { currentEntry = underlying(i0); i0 += 1 } while (currentEntry == null && i0 < iN) + currentEntry != null + }) + def substep(): Sub = { + if (iN-1 > i0) { + val half = (i0+iN) >>> 1 + val ans = semiclone(half) + i0 = half + ans + } + else null + } +} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection. + */ +abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) + with AnyStepper[A] +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Double`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextDouble`. + */ +abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) + with DoubleStepper +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Int`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextInt`. + */ +abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) + with IntStepper +{} + +/** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` + * and interpreting the contents as the elements of a collection of `Long`s. Subclasses + * are responsible for unboxing the `AnyRef` inside `nextLong`. + */ +abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) + extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index eb65c97..054e93a 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -23,7 +23,10 @@ class StepConvertersTest { def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } } - def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { IFFY(x)(correctSpec) } + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + } def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) @@ -49,7 +52,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[String]("salmon").buffered.stepper ) - IFFY( co.IndexedSeq[String]("salmon").stepper ) + good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) IFFY( co.Iterator[String]("salmon").stepper ) @@ -69,7 +72,7 @@ class StepConvertersTest { IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.HashSet[String]("salmon").stepper ) - IFFY( ci.IndexedSeq[String]("salmon").stepper ) + good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) IFFY( ci.Iterable[String]("salmon").stepper ) IFFY( ci.LinearSeq[String]("salmon").stepper ) @@ -106,7 +109,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashSet[String]("salmon").stepper ) - IFFY( cm.IndexedSeq[String]("salmon").stepper ) + good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) IFFY( cm.LinearSeq[String]("salmon").stepper ) @@ -145,7 +148,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Double](3.14159).buffered.stepper ) - IFFY( co.IndexedSeq[Double](3.14159).stepper ) + good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) IFFY( co.Iterator[Double](3.14159).stepper ) @@ -165,7 +168,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) - IFFY( ci.IndexedSeq[Double](3.14159).stepper ) + good( ci.IndexedSeq[Double](3.14159).stepper ) //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) IFFY( ci.LinearSeq[Double](3.14159).stepper ) @@ -202,7 +205,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) good( cm.HashSet[Double](3.14159).stepper ) - IFFY( cm.IndexedSeq[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) IFFY( cm.LinearSeq[Double](3.14159).stepper ) @@ -247,7 +250,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Int](654321).buffered.stepper ) - IFFY( co.IndexedSeq[Int](654321).stepper ) + good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) IFFY( co.Iterator[Int](654321).stepper ) @@ -267,7 +270,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.HashSet[Int](654321).stepper ) - IFFY( ci.IndexedSeq[Int](654321).stepper ) + good( ci.IndexedSeq[Int](654321).stepper ) //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) IFFY( ci.Iterable[Int](654321).stepper ) IFFY( ci.LinearSeq[Int](654321).stepper ) @@ -304,7 +307,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) good( cm.HashSet[Int](654321).stepper ) - IFFY( cm.IndexedSeq[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) IFFY( cm.LinearSeq[Int](654321).stepper ) @@ -345,7 +348,7 @@ class StepConvertersTest { // Collection section IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) - IFFY( co.IndexedSeq[Long](0x123456789L).stepper ) + good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) IFFY( co.Iterator[Long](0x123456789L).stepper ) @@ -365,7 +368,7 @@ class StepConvertersTest { //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) - IFFY( ci.IndexedSeq[Long](0x123456789L).stepper ) + good( ci.IndexedSeq[Long](0x123456789L).stepper ) //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) @@ -402,7 +405,7 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) good( cm.HashSet[Long](0x123456789L).stepper ) - IFFY( cm.IndexedSeq[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) @@ -439,7 +442,7 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) - IFFY( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) + _eh_( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) } From ffeb369063f0362340c44e38b5e174e025b137ae Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 10 Oct 2015 18:25:40 -0700 Subject: [PATCH 054/340] LinearSeq conversions in. --- .../scala/compat/java8/StepConverters.scala | 55 ++++++++++++ .../java8/collectionImpl/StepsWithTail.scala | 86 +++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 80 ++++++++--------- 3 files changed, 181 insertions(+), 40 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ea7093b..b7b8f6d 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -98,6 +98,38 @@ package converterImpls { def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } + private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) + extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) + } + + private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) + extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) + } + + private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) + extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) + } + + private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) + extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) + } + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -313,6 +345,22 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } + final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) + } + + final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) + } + + final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) + } + + final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) + } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } @@ -413,6 +461,7 @@ package converterImpls { implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) } trait Priority3StepConverters extends Priority4StepConverters { @@ -420,6 +469,12 @@ package converterImpls { implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = new RichIndexedSeqCanStep[A](underlying) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) + implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = + new RichDoubleLinearSeqCanStep[CC](underlying) + implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = + new RichIntLinearSeqCanStep[CC](underlying) + implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = + new RichLongLinearSeqCanStep[CC](underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala new file mode 100644 index 0000000..464880b --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala @@ -0,0 +1,86 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a collection with a fast tail operation. + * Because of how Java 8 streams subdivide their spliterators, we do this by chunking a bit at + * a time, generating a long chain of chunks. These won't necessarily all be the same size, + * but if there are enough hopefully it won't matter. + * + * Subclasses MUST decrement `maxN` when consuming elements, or this will not work! + */ +abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { + private var nextChunkSize: Int = 0 + protected def myIsEmpty(cc: CC): Boolean + protected def myTailOf(cc: CC): CC + def prepareParallelOperation(): this.type = { + if (maxN >= Int.MaxValue && nextChunkSize == 0) { + // Need parallel context to know whether to run this or not! + var u = underlying + var i = 0 + while (i < 1024 && !myIsEmpty(u)) { u = myTailOf(u); i += 1 } + if (i < 1024) maxN = i + else nextChunkSize = 64 // Guaranteed at least 16 chunks + } + this + } + def semiclone(chunk: Int): Semi + def characteristics(): Int = if (maxN < Int.MaxValue) Ordered | Sized | SubSized else Ordered + def estimateSize(): Long = if (maxN < Int.MaxValue) maxN else Long.MaxValue + def hasNext(): Boolean = if (maxN < Int.MaxValue) maxN > 0 else if (myIsEmpty(underlying)) { maxN = 0; false } else true + def substep(): Sub = { + prepareParallelOperation() + maxN match { + case x if x < 2 => null + case x if x >= Int.MaxValue => + var u = underlying + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) // Use bottom two bits to count up + while (i < n && !myIsEmpty(u)) { + u = myTailOf(u) + i += 1 + } + if (myIsEmpty(u)) { + maxN = i + substep() // Different branch now, recursion is an easy way to get it + } + else { + val sub = semiclone(n) + underlying = u + if ((nextChunkSize & 3) == 3) nextChunkSize = if (n < 0x40000000) 2*n else n else nextChunkSize += 1 + sub + } + case x => + var half = x.toInt >>> 1 + val sub = semiclone(half) + maxN -= half + while (half > 0) { underlying = myTailOf(underlying); half -= 1 } + sub + } + } +} + +/** Abstracts the operation of stepping over a generic indexable collection */ +abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, AnyStepper[A], STA](_underlying, _maxN) + with AnyStepper[A] +{} + +/** Abstracts the operation of stepping over an indexable collection of Doubles */ +abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, DoubleStepper, STD](_underlying, _maxN) + with DoubleStepper +{} + +/** Abstracts the operation of stepping over an indexable collection of Ints */ +abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, IntStepper, STI](_underlying, _maxN) + with IntStepper +{} + +/** Abstracts the operation of stepping over an indexable collection of Longs */ +abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) + extends AbstractStepsWithTail[CC, LongStepper, STL](_underlying, _maxN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 054e93a..2a19eb0 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -56,7 +56,7 @@ class StepConvertersTest { IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) IFFY( co.Iterator[String]("salmon").stepper ) - IFFY( co.LinearSeq[String]("salmon").stepper ) + good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) @@ -75,20 +75,20 @@ class StepConvertersTest { good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) IFFY( ci.Iterable[String]("salmon").stepper ) - IFFY( ci.LinearSeq[String]("salmon").stepper ) - IFFY( ci.List[String]("salmon").stepper ) + good( ci.LinearSeq[String]("salmon").stepper ) + good( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) - IFFY( ci.Queue[String]("salmon").stepper ) + good( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) - IFFY( ci.Stack[String]("salmon").stepper ) - IFFY( ci.Stream[String]("salmon").stepper ) - IFFY( ci.Stream[String]("salmon").view.stepper ) + good( ci.Stack[String]("salmon").stepper ) + good( ci.Stream[String]("salmon").stepper ) + _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) @@ -112,17 +112,17 @@ class StepConvertersTest { good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) - IFFY( cm.LinearSeq[String]("salmon").stepper ) + good( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) - IFFY( cm.MutableList[String]("salmon").stepper ) + good( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) - IFFY( cm.Queue[String]("salmon").stepper ) + good( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) IFFY( cm.Seq[String]("salmon").stepper ) IFFY( cm.Set[String]("salmon").stepper ) @@ -152,7 +152,7 @@ class StepConvertersTest { IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) IFFY( co.Iterator[Double](3.14159).stepper ) - IFFY( co.LinearSeq[Double](3.14159).stepper ) + good( co.LinearSeq[Double](3.14159).stepper ) //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) @@ -171,20 +171,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Double](3.14159).stepper ) //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) - IFFY( ci.LinearSeq[Double](3.14159).stepper ) - IFFY( ci.List[Double](3.14159).stepper ) + good( ci.LinearSeq[Double](3.14159).stepper ) + good( ci.List[Double](3.14159).stepper ) //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) - IFFY( ci.Queue[Double](3.14159).stepper ) + good( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) - IFFY( ci.Stack[Double](3.14159).stepper ) - IFFY( ci.Stream[Double](3.14159).stepper ) - IFFY( ci.Stream[Double](3.14159).view.stepper ) + good( ci.Stack[Double](3.14159).stepper ) + good( ci.Stream[Double](3.14159).stepper ) + _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) @@ -208,17 +208,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) - IFFY( cm.LinearSeq[Double](3.14159).stepper ) + good( cm.LinearSeq[Double](3.14159).stepper ) //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) - IFFY( cm.MutableList[Double](3.14159).stepper ) + good( cm.MutableList[Double](3.14159).stepper ) //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) - IFFY( cm.Queue[Double](3.14159).stepper ) + good( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) IFFY( cm.Seq[Double](3.14159).stepper ) IFFY( cm.Set[Double](3.14159).stepper ) @@ -254,7 +254,7 @@ class StepConvertersTest { IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) IFFY( co.Iterator[Int](654321).stepper ) - IFFY( co.LinearSeq[Int](654321).stepper ) + good( co.LinearSeq[Int](654321).stepper ) //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) @@ -273,20 +273,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Int](654321).stepper ) //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) IFFY( ci.Iterable[Int](654321).stepper ) - IFFY( ci.LinearSeq[Int](654321).stepper ) - IFFY( ci.List[Int](654321).stepper ) + good( ci.LinearSeq[Int](654321).stepper ) + good( ci.List[Int](654321).stepper ) //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.ListSet[Int](654321).stepper ) //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) - IFFY( ci.Queue[Int](654321).stepper ) + good( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.SortedSet[Int](654321).stepper ) - IFFY( ci.Stack[Int](654321).stepper ) - IFFY( ci.Stream[Int](654321).stepper ) - IFFY( ci.Stream[Int](654321).view.stepper ) + good( ci.Stack[Int](654321).stepper ) + good( ci.Stream[Int](654321).stepper ) + _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( ci.TreeSet[Int](654321).stepper ) @@ -310,17 +310,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) - IFFY( cm.LinearSeq[Int](654321).stepper ) + good( cm.LinearSeq[Int](654321).stepper ) //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) - IFFY( cm.MutableList[Int](654321).stepper ) + good( cm.MutableList[Int](654321).stepper ) //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) - IFFY( cm.Queue[Int](654321).stepper ) + good( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) IFFY( cm.Seq[Int](654321).stepper ) IFFY( cm.Set[Int](654321).stepper ) @@ -352,7 +352,7 @@ class StepConvertersTest { IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) IFFY( co.Iterator[Long](0x123456789L).stepper ) - IFFY( co.LinearSeq[Long](0x123456789L).stepper ) + good( co.LinearSeq[Long](0x123456789L).stepper ) //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) @@ -371,20 +371,20 @@ class StepConvertersTest { good( ci.IndexedSeq[Long](0x123456789L).stepper ) //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) - IFFY( ci.LinearSeq[Long](0x123456789L).stepper ) - IFFY( ci.List[Long](0x123456789L).stepper ) + good( ci.LinearSeq[Long](0x123456789L).stepper ) + good( ci.List[Long](0x123456789L).stepper ) //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) - IFFY( ci.Queue[Long](0x123456789L).stepper ) + good( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) - IFFY( ci.Stack[Long](0x123456789L).stepper ) - IFFY( ci.Stream[Long](0x123456789L).stepper ) - IFFY( ci.Stream[Long](0x123456789L).view.stepper ) + good( ci.Stack[Long](0x123456789L).stepper ) + good( ci.Stream[Long](0x123456789L).stepper ) + _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) @@ -408,17 +408,17 @@ class StepConvertersTest { good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) - IFFY( cm.LinearSeq[Long](0x123456789L).stepper ) + good( cm.LinearSeq[Long](0x123456789L).stepper ) //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) - IFFY( cm.MutableList[Long](0x123456789L).stepper ) + good( cm.MutableList[Long](0x123456789L).stepper ) //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) - IFFY( cm.Queue[Long](0x123456789L).stepper ) + good( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) IFFY( cm.Seq[Long](0x123456789L).stepper ) IFFY( cm.Set[Long](0x123456789L).stepper ) From a221edc3312075cef4781f6316b52558126f84b8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 17:37:33 -0700 Subject: [PATCH 055/340] Added iterator interface. Probably need to have it store initial segment like WithTail does. Leave that for speed tests later. --- .../scala/compat/java8/StepConverters.scala | 44 ++++++++ .../collectionImpl/StepsLikeIterator.scala | 106 ++++++++++++++++++ .../compat/java8/StepConvertersTest.scala | 16 +-- 3 files changed, 158 insertions(+), 8 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index b7b8f6d..01d9501 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -122,6 +122,30 @@ package converterImpls { def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) } + private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) + extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { + def semiclone() = new StepsAnyIterator(null) + def next() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) + extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { + def semiclone() = new StepsDoubleIterator(null) + def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsIntIterator(_underlying: Iterator[Int]) + extends StepsIntLikeIterator[StepsIntIterator](_underlying) { + def semiclone() = new StepsIntIterator(null) + def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next + } + + private[java8] class StepsLongIterator(_underlying: Iterator[Long]) + extends StepsLongLikeIterator[StepsLongIterator](_underlying) { + def semiclone() = new StepsLongIterator(null) + def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next + } + private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty @@ -361,6 +385,22 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) } + final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) + } + + final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) + } + + final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntIterator(underlying) + } + + final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongIterator(underlying) + } + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } @@ -475,6 +515,7 @@ package converterImpls { new RichIntLinearSeqCanStep[CC](underlying) implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) + implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -496,6 +537,9 @@ package converterImpls { implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) + implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) + implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala new file mode 100644 index 0000000..972b989 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala @@ -0,0 +1,106 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Common functionality for Steppers that step through an Iterator, caching the results as needed when a split is requested. */ +abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { + final protected var nextChunkSize = 16 + final protected var proxied: SP = null + def semiclone(): Semi // Must initialize with null iterator! + def characteristics(): Int = if (proxied ne null) Ordered | Sized | SubSized else Ordered + def estimateSize(): Long = if (proxied ne null) proxied.knownSize else Long.MaxValue + def hasNext(): Boolean = if (proxied ne null) proxied.hasStep else underlying.hasNext +} + +/** Abstracts the operation of stepping over an iterator (that needs to be cached when splitting) */ +abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) + extends AbstractStepsLikeIterator[A, AnyStepper[A], SLI](_underlying) + with AnyStepper[A] +{ + override def substep(): AnyStepper[A] = if (proxied ne null) proxied.substep else { + val acc = new Accumulator[A] + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Doubles (needs caching when split) */ +abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) + extends AbstractStepsLikeIterator[Double, DoubleStepper, SLI](_underlying) + with DoubleStepper +{ + override def substep(): DoubleStepper = if (proxied ne null) proxied.substep else { + val acc = new DoubleAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Ints (needs caching when split) */ +abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) + extends AbstractStepsLikeIterator[Int, IntStepper, SLI](_underlying) + with IntStepper +{ + override def substep(): IntStepper = if (proxied ne null) proxied.substep else { + val acc = new IntAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} + +/** Abstracts the operation of stepping over an iterator of Longs (needs caching when split) */ +abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) + extends AbstractStepsLikeIterator[Long, LongStepper, SLI](_underlying) + with LongStepper +{ + override def substep: LongStepper = if (proxied ne null) proxied.substep else { + val acc = new LongAccumulator + var i = 0 + val n = (nextChunkSize & 0xFFFFFFFC) + while (i < n && underlying.hasNext) { acc += underlying.next; i += 1 } + if (i < n || !underlying.hasNext) { + proxied = acc.stepper + proxied.substep + } + else { + val ans = semiclone() + ans.proxied = acc.stepper + nextChunkSize = if ((nextChunkSize&3) == 3) { if (n < 0x40000000) n*2 else n } else nextChunkSize + 1 + ans + } + } +} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 2a19eb0..1104a11 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -51,11 +51,11 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) // Collection section - IFFY( co.Iterator[String]("salmon").buffered.stepper ) + good( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) - IFFY( co.Iterator[String]("salmon").stepper ) + good( co.Iterator[String]("salmon").stepper ) good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) IFFY( co.Seq[String]("salmon").stepper ) @@ -147,11 +147,11 @@ class StepConvertersTest { //Double-specific tests // Collection section - IFFY( co.Iterator[Double](3.14159).buffered.stepper ) + good( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) - IFFY( co.Iterator[Double](3.14159).stepper ) + good( co.Iterator[Double](3.14159).stepper ) good( co.LinearSeq[Double](3.14159).stepper ) //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) IFFY( co.Seq[Double](3.14159).stepper ) @@ -249,11 +249,11 @@ class StepConvertersTest { good( (1 until 2).stepper ) // Collection section - IFFY( co.Iterator[Int](654321).buffered.stepper ) + good( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) - IFFY( co.Iterator[Int](654321).stepper ) + good( co.Iterator[Int](654321).stepper ) good( co.LinearSeq[Int](654321).stepper ) //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) IFFY( co.Seq[Int](654321).stepper ) @@ -347,11 +347,11 @@ class StepConvertersTest { good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) // Collection section - IFFY( co.Iterator[Long](0x123456789L).buffered.stepper ) + good( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) - IFFY( co.Iterator[Long](0x123456789L).stepper ) + good( co.Iterator[Long](0x123456789L).stepper ) good( co.LinearSeq[Long](0x123456789L).stepper ) //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) From f9d4e35b340c592be64687ebb4a548058b72c2b9 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 18:29:29 -0700 Subject: [PATCH 056/340] Added key and value steppers to maps. --- .../scala/compat/java8/StepConverters.scala | 36 +++ .../compat/java8/StepConvertersTest.scala | 224 +++++++++++++----- 2 files changed, 197 insertions(+), 63 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 01d9501..5033c97 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -461,6 +461,35 @@ package converterImpls { } } + final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal { + def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) + def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) + } + + final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal { + def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) + } + + final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal { + def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) + } + + final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal { + def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) + } + + final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal { + def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) + } + + final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal { + def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) + } + + final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal { + def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) + } + final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { def stepper: AnyStepper[A] = { val acc = new Accumulator[A] @@ -502,6 +531,7 @@ package converterImpls { implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } trait Priority3StepConverters extends Priority4StepConverters { @@ -516,6 +546,12 @@ package converterImpls { implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 1104a11..72c9caa 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -58,10 +58,14 @@ class StepConvertersTest { good( co.Iterator[String]("salmon").stepper ) good( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + good( co.Map[String, String]("fish" -> "salmon").keyStepper ) + good( co.Map[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) IFFY( co.Set[String]("salmon").stepper ) IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + good( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + good( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) @@ -70,27 +74,41 @@ class StepConvertersTest { // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) + good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + good( ci.IntMap[String](123456 -> "salmon").valueStepper ) IFFY( ci.Iterable[String]("salmon").stepper ) good( ci.LinearSeq[String]("salmon").stepper ) good( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + good( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + good( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + good( ci.Map[String, String]("fish" -> "salmon").keyStepper ) + good( ci.Map[String, String]("fish" -> "salmon").valueStepper ) good( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + good( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) good( ci.Stack[String]("salmon").stepper ) good( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + good( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) @@ -98,9 +116,13 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) + good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + good( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) + good( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) good( (Array("salmon"): cm.ArrayOps[String]).stepper ) @@ -108,19 +130,30 @@ class StepConvertersTest { _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) good( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + good( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + good( cm.Map[String, String]("fish" -> "salmon").keyStepper ) + good( cm.Map[String, String]("fish" -> "salmon").valueStepper ) good( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) good( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) @@ -132,6 +165,8 @@ class StepConvertersTest { IFFY( cm.TreeSet[String]("salmon").stepper ) IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) // Java 6 converters section @@ -153,11 +188,13 @@ class StepConvertersTest { IFFY( co.Iterable[Double](3.14159).view.stepper ) good( co.Iterator[Double](3.14159).stepper ) good( co.LinearSeq[Double](3.14159).stepper ) - //IFFY( co.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) IFFY( co.Set[Double](3.14159).stepper ) - //IFFY( co.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.SortedSet[Double](3.14159).stepper ) IFFY( co.Traversable[Double](3.14159).stepper ) IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) @@ -165,58 +202,70 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(3.14159, Nil).stepper ) - //IFFY( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).stepper ) - //IFFY( ci.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) + good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) - //IFFY( ci.IntMap[Double](123456 -> 3.14159).stepper ) + good( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) good( ci.LinearSeq[Double](3.14159).stepper ) good( ci.List[Double](3.14159).stepper ) - //IFFY( ci.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) - //IFFY( ci.LongMap[Double](9876543210L -> 3.14159).stepper ) - //IFFY( ci.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + good( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) - //IFFY( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) good( ci.Stack[Double](3.14159).stepper ) good( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) - //IFFY( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) - //IFFY( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).stepper ) + good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) + good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) - //IFFY( cm.AnyRefMap[Double,Double](2.718281828 -> 3.14159).stepper ) + good( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - //IFFY( cm.HashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) good( cm.LinearSeq[Double](3.14159).stepper ) - //IFFY( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) - //IFFY( cm.ListMap[Double, Double](2.718281828 -> 3.14159).stepper ) - //IFFY( cm.LongMap[Double](9876543210L -> 3.14159).stepper ) - //IFFY( cm.Map[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + good( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.MutableList[Double](3.14159).stepper ) - //IFFY( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) good( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) @@ -227,14 +276,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Double](3.14159).stepper ) IFFY( cm.TreeSet[Double](3.14159).stepper ) IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) - //IFFY( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).stepper ) + good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).stepper ) - //IFFY( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).stepper ) + good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) + good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) } @Test @@ -247,6 +299,9 @@ class StepConvertersTest { good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) + good( ci.IntMap[String](123456 -> "salmon").keyStepper ) + good( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) + good( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) // Collection section good( co.Iterator[Int](654321).buffered.stepper ) @@ -255,11 +310,13 @@ class StepConvertersTest { IFFY( co.Iterable[Int](654321).view.stepper ) good( co.Iterator[Int](654321).stepper ) good( co.LinearSeq[Int](654321).stepper ) - //IFFY( co.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) IFFY( co.Set[Int](654321).stepper ) - //IFFY( co.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.SortedSet[Int](654321).stepper ) IFFY( co.Traversable[Int](654321).stepper ) IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) @@ -267,58 +324,71 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(654321, Nil).stepper ) - //IFFY( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).stepper ) - //IFFY( ci.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) + good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) - //IFFY( ci.IntMap[Int](123456 -> 654321).stepper ) + good( ci.IntMap[Int](123456 -> 654321).keyStepper ) + good( ci.IntMap[Int](123456 -> 654321).valueStepper ) IFFY( ci.Iterable[Int](654321).stepper ) good( ci.LinearSeq[Int](654321).stepper ) good( ci.List[Int](654321).stepper ) - //IFFY( ci.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.ListSet[Int](654321).stepper ) - //IFFY( ci.LongMap[Int](9876543210L -> 654321).stepper ) - //IFFY( ci.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) + good( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) good( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) - //IFFY( ci.SortedMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.SortedSet[Int](654321).stepper ) good( ci.Stack[Int](654321).stepper ) good( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) - //IFFY( ci.TreeMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) - //IFFY( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).stepper ) + good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) + good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) - //IFFY( cm.AnyRefMap[Int,Int](0xDEEDED -> 654321).stepper ) + good( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - //IFFY( cm.HashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) good( cm.LinearSeq[Int](654321).stepper ) - //IFFY( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) - //IFFY( cm.ListMap[Int, Int](0xDEEDED -> 654321).stepper ) - //IFFY( cm.LongMap[Int](9876543210L -> 654321).stepper ) - //IFFY( cm.Map[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) + good( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.MutableList[Int](654321).stepper ) - //IFFY( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) good( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) @@ -329,14 +399,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Int](654321).stepper ) IFFY( cm.TreeSet[Int](654321).stepper ) IFFY( cm.UnrolledBuffer[Int](654321).stepper ) - //IFFY( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).stepper ) + good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Int, Int](0xDEEDED -> 654321).stepper ) - //IFFY( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).stepper ) + good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) + good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) } @Test @@ -345,6 +418,12 @@ class StepConvertersTest { // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + good( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) + good( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) + good( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + good( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + good( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) + good( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) // Collection section good( co.Iterator[Long](0x123456789L).buffered.stepper ) @@ -353,11 +432,13 @@ class StepConvertersTest { IFFY( co.Iterable[Long](0x123456789L).view.stepper ) good( co.Iterator[Long](0x123456789L).stepper ) good( co.LinearSeq[Long](0x123456789L).stepper ) - //IFFY( co.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) IFFY( co.Set[Long](0x123456789L).stepper ) - //IFFY( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.SortedSet[Long](0x123456789L).stepper ) IFFY( co.Traversable[Long](0x123456789L).stepper ) IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) @@ -365,58 +446,72 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(0x123456789L, Nil).stepper ) - //IFFY( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).stepper ) - //IFFY( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) + good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) - //IFFY( ci.IntMap[Long](123456 -> 0x123456789L).stepper ) + good( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) good( ci.LinearSeq[Long](0x123456789L).stepper ) good( ci.List[Long](0x123456789L).stepper ) - //IFFY( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) - //IFFY( ci.LongMap[Long](9876543210L -> 0x123456789L).stepper ) - //IFFY( ci.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + good( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) - //IFFY( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) good( ci.Stack[Long](0x123456789L).stepper ) good( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) - //IFFY( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) - //IFFY( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).stepper ) + good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) + good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) - //IFFY( cm.AnyRefMap[Long,Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - //IFFY( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) good( cm.LinearSeq[Long](0x123456789L).stepper ) - //IFFY( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) - //IFFY( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) - //IFFY( cm.LongMap[Long](9876543210L -> 0x123456789L).stepper ) - //IFFY( cm.Map[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + good( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.MutableList[Long](0x123456789L).stepper ) - //IFFY( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) good( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) @@ -427,14 +522,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Long](0x123456789L).stepper ) IFFY( cm.TreeSet[Long](0x123456789L).stepper ) IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) - //IFFY( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) + good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) // Java 6 converters section // Concurrent section - //IFFY( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).stepper ) - //IFFY( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).stepper ) + good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) + good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) } @Test From d5bb5895ff3948cdab76e73238f3a3c587a0e048 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 11 Oct 2015 18:51:48 -0700 Subject: [PATCH 057/340] Distinguish between good and sorta acceptable (sequential traversal) access for Stepper in tests. --- .../compat/java8/StepConvertersTest.scala | 430 +++++++++--------- 1 file changed, 223 insertions(+), 207 deletions(-) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 72c9caa..681f16b 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -10,7 +10,7 @@ class StepConvertersTest { import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } - def isAcc[X](x: X) = x match { + def isAcc[X](x: X): Boolean = x match { case _: AccumulatorStepper[_] => true case _: DoubleAccumulatorStepper => true case _: IntAccumulatorStepper => true @@ -18,6 +18,12 @@ class StepConvertersTest { case _ => false } + def isLin[X](x: X): Boolean = x match { + case _: AbstractStepsLikeIterator[_, _, _] => true + case _: AbstractStepsWithTail[_, _, _] => true + case _ => false + } + trait SpecCheck { def apply[X](x: X): Boolean } object SpecCheck { def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } @@ -34,10 +40,16 @@ class StepConvertersTest { assert(isAcc(x)) } + def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + assert(!isAcc(x) && isLin(x)) + } + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x)) + assert(!isAcc(x) && !isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { @@ -51,21 +63,21 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) // Collection section - good( co.Iterator[String]("salmon").buffered.stepper ) + Okay( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").stepper ) IFFY( co.Iterable[String]("salmon").view.stepper ) - good( co.Iterator[String]("salmon").stepper ) - good( co.LinearSeq[String]("salmon").stepper ) + Okay( co.Iterator[String]("salmon").stepper ) + Okay( co.LinearSeq[String]("salmon").stepper ) IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) - good( co.Map[String, String]("fish" -> "salmon").keyStepper ) - good( co.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.Seq[String]("salmon").stepper ) IFFY( co.Seq[String]("salmon").view.stepper ) IFFY( co.Set[String]("salmon").stepper ) IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) - good( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) - good( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) @@ -74,41 +86,41 @@ class StepConvertersTest { // Immutable section IFFY( ci.::("salmon", Nil).stepper ) IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) - good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) - good( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) - good( ci.IntMap[String](123456 -> "salmon").valueStepper ) + Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) IFFY( ci.Iterable[String]("salmon").stepper ) - good( ci.LinearSeq[String]("salmon").stepper ) - good( ci.List[String]("salmon").stepper ) + Okay( ci.LinearSeq[String]("salmon").stepper ) + Okay( ci.List[String]("salmon").stepper ) IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) - good( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.ListSet[String]("salmon").stepper ) IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) - good( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) - good( ci.Map[String, String]("fish" -> "salmon").keyStepper ) - good( ci.Map[String, String]("fish" -> "salmon").valueStepper ) - good( ci.Queue[String]("salmon").stepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.Queue[String]("salmon").stepper ) IFFY( ci.Seq[String]("salmon").stepper ) IFFY( ci.Set[String]("salmon").stepper ) IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) - good( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.SortedSet[String]("salmon").stepper ) - good( ci.Stack[String]("salmon").stepper ) - good( ci.Stream[String]("salmon").stepper ) + Okay( ci.Stack[String]("salmon").stepper ) + Okay( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) IFFY( ci.Traversable[String]("salmon").stepper ) IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) - good( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) - good( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) @@ -116,13 +128,13 @@ class StepConvertersTest { IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) - good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) - good( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) - good( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) - good( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) good( ((Array("salmon"): cm.WrappedArray[String]): cm.ArrayLike[String, cm.WrappedArray[String]]).stepper ) good( (Array("salmon"): cm.ArrayOps[String]).stepper ) @@ -130,32 +142,32 @@ class StepConvertersTest { _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) - good( cm.LinearSeq[String]("salmon").stepper ) + Okay( cm.LinearSeq[String]("salmon").stepper ) IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) - good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) - good( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) - good( cm.Map[String, String]("fish" -> "salmon").keyStepper ) - good( cm.Map[String, String]("fish" -> "salmon").valueStepper ) - good( cm.MutableList[String]("salmon").stepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.MutableList[String]("salmon").stepper ) IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.PriorityQueue[String]("salmon").stepper ) - good( cm.Queue[String]("salmon").stepper ) + Okay( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) IFFY( cm.Seq[String]("salmon").stepper ) IFFY( cm.Set[String]("salmon").stepper ) @@ -165,15 +177,19 @@ class StepConvertersTest { IFFY( cm.TreeSet[String]("salmon").stepper ) IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) - good( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) - good( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) // Java 6 converters section // Concurrent section IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).keyStepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).valueStepper ) } @Test @@ -182,19 +198,19 @@ class StepConvertersTest { //Double-specific tests // Collection section - good( co.Iterator[Double](3.14159).buffered.stepper ) + Okay( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).stepper ) IFFY( co.Iterable[Double](3.14159).view.stepper ) - good( co.Iterator[Double](3.14159).stepper ) - good( co.LinearSeq[Double](3.14159).stepper ) - good( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.Iterator[Double](3.14159).stepper ) + Okay( co.LinearSeq[Double](3.14159).stepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.Seq[Double](3.14159).stepper ) IFFY( co.Seq[Double](3.14159).view.stepper ) IFFY( co.Set[Double](3.14159).stepper ) - good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( co.SortedSet[Double](3.14159).stepper ) IFFY( co.Traversable[Double](3.14159).stepper ) IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) @@ -202,72 +218,72 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(3.14159, Nil).stepper ) - good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) - good( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) + Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) - good( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) - good( ci.LinearSeq[Double](3.14159).stepper ) - good( ci.List[Double](3.14159).stepper ) - good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.LinearSeq[Double](3.14159).stepper ) + Okay( ci.List[Double](3.14159).stepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.ListSet[Double](3.14159).stepper ) - good( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) - good( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( ci.Queue[Double](3.14159).stepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.Queue[Double](3.14159).stepper ) IFFY( ci.Seq[Double](3.14159).stepper ) IFFY( ci.Set[Double](3.14159).stepper ) - good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.SortedSet[Double](3.14159).stepper ) - good( ci.Stack[Double](3.14159).stepper ) - good( ci.Stream[Double](3.14159).stepper ) + Okay( ci.Stack[Double](3.14159).stepper ) + Okay( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) IFFY( ci.Traversable[Double](3.14159).stepper ) - good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) - good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) - good( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) - good( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) + Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) - good( cm.LinearSeq[Double](3.14159).stepper ) - good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LinearSeq[Double](3.14159).stepper ) + Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) - good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) - good( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( cm.MutableList[Double](3.14159).stepper ) - good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.MutableList[Double](3.14159).stepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.PriorityQueue[Double](3.14159).stepper ) - good( cm.Queue[Double](3.14159).stepper ) + Okay( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) IFFY( cm.Seq[Double](3.14159).stepper ) IFFY( cm.Set[Double](3.14159).stepper ) @@ -276,17 +292,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Double](3.14159).stepper ) IFFY( cm.TreeSet[Double](3.14159).stepper ) IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) - good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - good( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) - good( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) } @Test @@ -299,24 +315,24 @@ class StepConvertersTest { good( ci.NumericRange(123456, 123458, 1).stepper ) IFFY( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) - good( ci.IntMap[String](123456 -> "salmon").keyStepper ) - good( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) - good( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) + Okay( ci.IntMap[String](123456 -> "salmon").keyStepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) // Collection section - good( co.Iterator[Int](654321).buffered.stepper ) + Okay( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).stepper ) IFFY( co.Iterable[Int](654321).view.stepper ) - good( co.Iterator[Int](654321).stepper ) - good( co.LinearSeq[Int](654321).stepper ) - good( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.Iterator[Int](654321).stepper ) + Okay( co.LinearSeq[Int](654321).stepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.Seq[Int](654321).stepper ) IFFY( co.Seq[Int](654321).view.stepper ) IFFY( co.Set[Int](654321).stepper ) - good( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( co.SortedSet[Int](654321).stepper ) IFFY( co.Traversable[Int](654321).stepper ) IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) @@ -324,73 +340,73 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(654321, Nil).stepper ) - good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) - good( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) + Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) - good( ci.IntMap[Int](123456 -> 654321).keyStepper ) - good( ci.IntMap[Int](123456 -> 654321).valueStepper ) + Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) + Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) IFFY( ci.Iterable[Int](654321).stepper ) - good( ci.LinearSeq[Int](654321).stepper ) - good( ci.List[Int](654321).stepper ) - good( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.LinearSeq[Int](654321).stepper ) + Okay( ci.List[Int](654321).stepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.ListSet[Int](654321).stepper ) - good( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) - good( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( ci.Queue[Int](654321).stepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.Queue[Int](654321).stepper ) IFFY( ci.Seq[Int](654321).stepper ) IFFY( ci.Set[Int](654321).stepper ) - good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.SortedSet[Int](654321).stepper ) - good( ci.Stack[Int](654321).stepper ) - good( ci.Stream[Int](654321).stepper ) + Okay( ci.Stack[Int](654321).stepper ) + Okay( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) IFFY( ci.Traversable[Int](654321).stepper ) - good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) - good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) - good( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) - good( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) + Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) - good( cm.LinearSeq[Int](654321).stepper ) - good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LinearSeq[Int](654321).stepper ) + Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) - good( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) - good( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( cm.MutableList[Int](654321).stepper ) - good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.MutableList[Int](654321).stepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.PriorityQueue[Int](654321).stepper ) - good( cm.Queue[Int](654321).stepper ) + Okay( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) IFFY( cm.Seq[Int](654321).stepper ) IFFY( cm.Set[Int](654321).stepper ) @@ -399,17 +415,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Int](654321).stepper ) IFFY( cm.TreeSet[Int](654321).stepper ) IFFY( cm.UnrolledBuffer[Int](654321).stepper ) - good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - good( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) - good( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) } @Test @@ -418,27 +434,27 @@ class StepConvertersTest { // Long-specific tests good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) - good( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) - good( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) - good( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) - good( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) - good( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) - good( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) // Collection section - good( co.Iterator[Long](0x123456789L).buffered.stepper ) + Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).stepper ) IFFY( co.Iterable[Long](0x123456789L).view.stepper ) - good( co.Iterator[Long](0x123456789L).stepper ) - good( co.LinearSeq[Long](0x123456789L).stepper ) - good( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.Iterator[Long](0x123456789L).stepper ) + Okay( co.LinearSeq[Long](0x123456789L).stepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.Seq[Long](0x123456789L).stepper ) IFFY( co.Seq[Long](0x123456789L).view.stepper ) IFFY( co.Set[Long](0x123456789L).stepper ) - good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( co.SortedSet[Long](0x123456789L).stepper ) IFFY( co.Traversable[Long](0x123456789L).stepper ) IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) @@ -446,74 +462,74 @@ class StepConvertersTest { // Immutable section IFFY( ci.::(0x123456789L, Nil).stepper ) - good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) - good( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) + Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) - good( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) - good( ci.LinearSeq[Long](0x123456789L).stepper ) - good( ci.List[Long](0x123456789L).stepper ) - good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.LinearSeq[Long](0x123456789L).stepper ) + Okay( ci.List[Long](0x123456789L).stepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.ListSet[Long](0x123456789L).stepper ) - good( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) - good( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) - good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( ci.Queue[Long](0x123456789L).stepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.Queue[Long](0x123456789L).stepper ) IFFY( ci.Seq[Long](0x123456789L).stepper ) IFFY( ci.Set[Long](0x123456789L).stepper ) - good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.SortedSet[Long](0x123456789L).stepper ) - good( ci.Stack[Long](0x123456789L).stepper ) - good( ci.Stream[Long](0x123456789L).stepper ) + Okay( ci.Stack[Long](0x123456789L).stepper ) + Okay( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) IFFY( ci.Traversable[Long](0x123456789L).stepper ) - good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) - good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) - good( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) - good( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) + Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) - good( cm.LinearSeq[Long](0x123456789L).stepper ) - good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LinearSeq[Long](0x123456789L).stepper ) + Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) - good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) - good( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) - good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( cm.MutableList[Long](0x123456789L).stepper ) - good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.MutableList[Long](0x123456789L).stepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) - good( cm.Queue[Long](0x123456789L).stepper ) + Okay( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) IFFY( cm.Seq[Long](0x123456789L).stepper ) IFFY( cm.Set[Long](0x123456789L).stepper ) @@ -522,17 +538,17 @@ class StepConvertersTest { IFFY( cm.Traversable[Long](0x123456789L).stepper ) IFFY( cm.TreeSet[Long](0x123456789L).stepper ) IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) - good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) // Java 6 converters section // Concurrent section - good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - good( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) - good( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) } @Test From f13b0f3d05b272aa9024db2f06a1ea735bfe202e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 12 Oct 2015 20:50:07 -0700 Subject: [PATCH 058/340] Linked and regular HashMaps working. --- .../java8/runtime/CollectionInternals.java | 1 + .../scala/compat/java8/StepConverters.scala | 264 +++++++++++++++++- .../compat/java8/StepConvertersTest.scala | 42 +-- 3 files changed, 278 insertions(+), 29 deletions(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 1f30ea3..c5071bc 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -2,6 +2,7 @@ public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } + public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 5033c97..65bc93c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -321,6 +321,120 @@ package converterImpls { def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) } + private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) + extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) + } + + private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) + } + + private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) + } + + private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) + } + + private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) + } + + private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) + } + + private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) + } + + private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) + } + + private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) + } + + private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) + } + + private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) + extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) + } + + private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) + extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) + } + + private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) + extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) + } + + private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) + extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -436,7 +550,105 @@ package converterImpls { new StepsLongFlatHashTable(tbl, 0, tbl.length) } } + + final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) extends AnyVal { + @inline def keyStepper: AnyStepper[K] = { + val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) + new StepsAnyHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) extends AnyVal { + @inline def keyStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) + new StepsDoubleHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) extends AnyVal { + @inline def keyStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) + new StepsIntHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) extends AnyVal { + @inline def keyStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) + new StepsLongHashTableKey(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { + @inline def stepper: AnyStepper[(K,V)] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTable(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { + @inline def valueStepper: AnyStepper[V] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) extends AnyVal { + @inline def valueStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) + new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) extends AnyVal { + @inline def valueStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) + new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) extends AnyVal { + @inline def valueStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) + new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { + @inline def stepper: AnyStepper[(K,V)] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTable(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { + @inline def valueStepper: AnyStepper[V] = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) extends AnyVal { + @inline def valueStepper: DoubleStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) + new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) + } + } + + final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) extends AnyVal { + @inline def valueStepper: IntStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) + new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) + } + } + final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) extends AnyVal { + @inline def valueStepper: LongStepper = { + val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) + new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) + } + } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 @@ -522,17 +734,39 @@ package converterImpls { } } - trait Priority5StepConverters { + trait Priority7StepConverters { implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) } - trait Priority4StepConverters extends Priority5StepConverters { + trait Priority6StepConverters extends Priority7StepConverters { implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) - implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } + + trait Priority5StepConverters extends Priority6StepConverters { + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) + } + + trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = + new RichHashTableKeyCanStep[K, HE](underlying) + implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableCanStep[K, V](underlying) + implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableValueCanStep[K, V](underlying) + implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableCanStep[K, V](underlying) + implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableValueCanStep[K, V](underlying) + } trait Priority3StepConverters extends Priority4StepConverters { implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) @@ -546,12 +780,24 @@ package converterImpls { implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = new RichLongLinearSeqCanStep[CC](underlying) implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) - implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) - implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) - implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) - implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) - implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) + implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = + new RichHashTableDoubleKeyCanStep[HE](underlying) + implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = + new RichHashTableIntKeyCanStep[HE](underlying) + implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = + new RichHashTableLongKeyCanStep[HE](underlying) + implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = + new RichDefaultHashTableDoubleValueCanStep[K](underlying) + implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = + new RichDefaultHashTableIntValueCanStep[K](underlying) + implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = + new RichDefaultHashTableLongValueCanStep[K](underlying) + implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = + new RichLinkedHashTableDoubleValueCanStep[K](underlying) + implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = + new RichLinkedHashTableIntValueCanStep[K](underlying) + implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = + new RichLinkedHashTableLongValueCanStep[K](underlying) } trait Priority2StepConverters extends Priority3StepConverters { diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 681f16b..855d9b9 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -43,13 +43,15 @@ class StepConvertersTest { def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x) && isLin(x)) + assert(!isAcc(x)) + assert(isLin(x)) } def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) - assert(!isAcc(x) && !isLin(x)) + assert(!isAcc(x)) + assert(!isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { @@ -141,17 +143,17 @@ class StepConvertersTest { good( cm.ArraySeq[String]("salmon").stepper ) _eh_( cm.ArrayStack[String]("salmon").stepper ) IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) - IFFY( cm.HashMap[String, String]("fish" -> "salmon").stepper ) - Okay( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) IFFY( cm.Iterable[String]("salmon").stepper ) Okay( cm.LinearSeq[String]("salmon").stepper ) - IFFY( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) - Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( cm.LinkedHashSet[String]("salmon").stepper ) IFFY( cm.ListBuffer[String]("salmon").stepper ) IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) @@ -263,15 +265,15 @@ class StepConvertersTest { good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) - Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) IFFY( cm.Iterable[Double](3.14159).stepper ) Okay( cm.LinearSeq[Double](3.14159).stepper ) - Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) IFFY( cm.ListBuffer[Double](3.14159).stepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) @@ -386,15 +388,15 @@ class StepConvertersTest { good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) - Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) IFFY( cm.Iterable[Int](654321).stepper ) Okay( cm.LinearSeq[Int](654321).stepper ) - Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( cm.LinkedHashSet[Int](654321).stepper ) IFFY( cm.ListBuffer[Int](654321).stepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) @@ -508,15 +510,15 @@ class StepConvertersTest { good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) - Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) IFFY( cm.Iterable[Long](0x123456789L).stepper ) Okay( cm.LinearSeq[Long](0x123456789L).stepper ) - Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) From fedc1eba242328f58e7281b85960860d5631a989 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 17 Oct 2015 20:40:25 -0700 Subject: [PATCH 059/340] Immutable HashMaps are now nicely steppable (and thus can be streamed). --- .../scala/compat/java8/StepConverters.scala | 147 ++++++++++++++++++ .../collectionImpl/StepsLikeImmHashMap.scala | 53 +++++++ .../collectionImpl/StepsLikeSliced.scala | 40 +++++ .../compat/java8/StepConvertersTest.scala | 18 +-- 4 files changed, 249 insertions(+), 9 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 65bc93c..c1bfbb0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -435,6 +435,114 @@ package converterImpls { new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) } + private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) + def next(): (K, V) = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.iterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) + def next(): K = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) + def next(): V = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) + extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) + extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) + extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) + extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) + extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE + } + + private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) + extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -648,6 +756,36 @@ package converterImpls { new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) } } + + final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal { + @inline def stepper: AnyStepper[(K, V)] = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + } + + final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal { + @inline def keyStepper: DoubleStepper = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal { + @inline def valueStepper: DoubleStepper = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) + } + + final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal { + @inline def keyStepper: IntStepper = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal { + @inline def valueStepper: IntStepper = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) + } + + final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal { + @inline def keyStepper: LongStepper = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) + } + + final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal { + @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) + } private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull @@ -798,6 +936,8 @@ package converterImpls { new RichLinkedHashTableIntValueCanStep[K](underlying) implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = new RichLinkedHashTableLongValueCanStep[K](underlying) + + implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -822,6 +962,13 @@ package converterImpls { implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) + + implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) + implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) + implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) + implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) + implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) + implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala new file mode 100644 index 0000000..169991c --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala @@ -0,0 +1,53 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over an immutable HashMap by slicing it into pieces. + * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the + * collection needs some sort of modification before transmission to the subclass. + */ +trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] +extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { + protected var theIterator: Iterator[A] = null + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int): Semi + override def characteristics() = Immutable + def hasNext(): Boolean = i < iN + def semiclone(halfHint: Int): Semi = + if (i >= iN) null + else underlying match { + case trie: collection.immutable.HashMap.HashTrieMap[K, V] => + val parts = if (i > i0) trie.drop(i-i0).split else trie.split + if (parts.length != 2) null + else { + val ans = demiclone(parts.head, 0, parts.head.size) + i = iN - parts.last.size + underlying = parts.last + ans.theIterator = theIterator + theIterator = null + i0 = i + ans + } + case _ => null + } +} + +abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLikeSliced[A, collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, A, AnyStepper[A], SIHM] +{} + +abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsDoubleLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Double, DoubleStepper, SIHM] +{} + +abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsIntLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Int, IntStepper, SIHM] +{} + +abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) + extends StepsLongLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) + with AbstractStepsLikeImmHashMap[K, V, Long, LongStepper, SIHM] +{} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala new file mode 100644 index 0000000..a6f2110 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala @@ -0,0 +1,40 @@ +package scala.compat.java8.collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a collection that can be sliced into pieces. + * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the + * collection needs some sort of modification before transmission to the subclass. + */ +abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { + protected var i0: Int = i + def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! + def characteristics(): Int = Ordered + def estimateSize(): Long = iN - i + def substep(): Sub = if (estimateSize > 0) semiclone((iN + i) >>> 1) else null +} + +/** Abstracts the operation of stepping over a generic collection that can be efficiently sliced or otherwise subdivided */ +abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) + with AnyStepper[A] +{} + +/** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ +abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) + with DoubleStepper +{} + +/** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ +abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) + with IntStepper +{} + +/** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ +abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) + extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) + with LongStepper +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 855d9b9..075e1eb 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -90,9 +90,9 @@ class StepConvertersTest { IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) - IFFY( ci.HashMap[String, String]("fish" -> "salmon").stepper ) - Okay( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) - Okay( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) @@ -222,8 +222,8 @@ class StepConvertersTest { IFFY( ci.::(3.14159, Nil).stepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) - Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) - Okay( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) IFFY( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) @@ -344,8 +344,8 @@ class StepConvertersTest { IFFY( ci.::(654321, Nil).stepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) - Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) - Okay( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) IFFY( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) @@ -466,8 +466,8 @@ class StepConvertersTest { IFFY( ci.::(0x123456789L, Nil).stepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) - Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) - Okay( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) IFFY( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) From 7413c0c52e667776addd08d90531977fcbd75eea Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 18 Oct 2015 17:56:08 -0700 Subject: [PATCH 060/340] BitSet added. --- .../java8/runtime/CollectionInternals.java | 11 ++ .../scala/compat/java8/StepConverters.scala | 102 +++++++++++++++++- .../StepsLikeTrieIterator.scala | 48 +++++++++ .../compat/java8/StepConvertersTest.scala | 14 +-- 4 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index c5071bc..ba6f6a6 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -1,5 +1,7 @@ package scala.compat.java8.runtime; +import scala.collection.immutable.*; // Don't rely on this! Refer to everything explicitly! + public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } @@ -9,4 +11,13 @@ public class CollectionInternals { public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } + public static scala.Tuple2< scala.Tuple2< scala.collection.Iterator, Object >, scala.collection.Iterator > trieIteratorSplit(scala.collection.Iterator it) { + if (it instanceof scala.collection.immutable.TrieIterator) { + scala.collection.immutable.TrieIterator trie = (scala.collection.immutable.TrieIterator)it; + return trie.split(); + } + return null; + } + public static long[] getBitSetInternals(scala.collection.mutable.BitSet bitSet) { return bitSet.elems(); } } + diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index c1bfbb0..ef39d0c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -543,6 +543,68 @@ package converterImpls { else throwNSEE } + private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) + extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { + protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) + def next(): A = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) + extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) + def nextDouble() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) + extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) + def nextInt() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) + extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) + def nextLong() = { val ans = underlying.next; i += 1; ans } + } + + private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) + extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { + private var mask: Long = (-1L) << (i & 0x3F) + private var cache: Long = underlying(i >>> 6) + private var found: Boolean = false + def semiclone(half: Int) = { + val ans = new StepsIntBitSet(underlying, i, half) + i = half + mask = (-1L) << (i & 0x3F) + cache = underlying(i >>> 6) + found = false + ans + } + def hasNext(): Boolean = found || ((i < iN) && { + while ((mask & cache) == 0) { + i += java.lang.Long.numberOfLeadingZeros(~mask) + if (i < 0 || i >= iN) { i = iN; return false } + mask = -1L + cache = underlying(i >>> 6) + } + var m = mask << 1 + while ((mask & cache) == (m & cache)) { + mask = m + m = mask << 1 + i += 1 + } + if (i < 0 || i >= iN) { + i = iN + false + } + else { + found = true + true + } + }) + def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE + } + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -787,6 +849,25 @@ package converterImpls { @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) } + final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal { + @inline def stepper: AnyStepper[A] = new StepsAnyImmHashSet(underlying.iterator, underlying.size) + } + + final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal { + def stepper: IntStepper = { + val bits: Array[Long] = underlying match { + case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) + case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) + case x => x.toBitMask + } + new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) + } + } + private[java8] object RichBitSetCanStep { + private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") + def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] + } + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { def characteristics() = NonNull def estimateSize = iN - i0 @@ -938,6 +1019,7 @@ package converterImpls { new RichLinkedHashTableLongValueCanStep[K](underlying) implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) + implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) } trait Priority2StepConverters extends Priority3StepConverters { @@ -969,6 +1051,8 @@ package converterImpls { implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) + + implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) } } @@ -992,15 +1076,15 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) } - implicit final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { + implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) } - implicit final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { + implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) } - implicit final class RichRangeCanStep(private val underlying: Range) extends AnyVal { + implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal { @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) } @@ -1012,6 +1096,18 @@ object StepConverters extends converterImpls.Priority2StepConverters { @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) } + implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal { + @inline def stepper: DoubleStepper = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + } + + implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal { + @inline def stepper: IntStepper = new StepsIntImmHashSet(underlying.iterator, underlying.size) + } + + implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal { + @inline def stepper: LongStepper = new StepsLongImmHashSet(underlying.iterator, underlying.size) + } + implicit class RichStringCanStep(val underlying: String) extends AnyVal { @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala new file mode 100644 index 0000000..631ed11 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala @@ -0,0 +1,48 @@ +package scala.compat.java8 +package collectionImpl + +import java.util.Spliterator +import Stepper._ + +/** Abstracts all the generic operations of stepping over a TrieIterator by asking itself to + * slice itself into pieces. Note that `i` must be kept up to date in subclasses. + */ +trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] +extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { + protected def demiclone(it: Iterator[A], N: Int): Semi + override def characteristics() = Immutable + def hasNext(): Boolean = underlying.hasNext + def semiclone(halfHint: Int): Semi = + if (!underlying.hasNext || i > iN-2) null + else runtime.CollectionInternals.trieIteratorSplit(underlying) match { + case null => null + case ((pre: Iterator[A], pno), post: Iterator[A]) => + val pn = (pno: Any) match { case i: Int => i; case _ => throw new Exception("Unexpected type") } + val ans = demiclone(pre, pn) + i += pn + underlying = post + i0 = i + ans + case _ => null + } +} + +abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) + extends StepsLikeSliced[A, Iterator[A], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[A, AnyStepper[A], STI] +{} + +abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) + extends StepsDoubleLikeSliced[Iterator[Double], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Double, DoubleStepper, STI] +{} + +abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) + extends StepsIntLikeSliced[Iterator[Int], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Int, IntStepper, STI] +{} + +abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) + extends StepsLongLikeSliced[Iterator[Long], STI](_underlying, 0, _N) + with AbstractStepsLikeTrieIterator[Long, LongStepper, STI] +{} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 075e1eb..c227463 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -93,7 +93,7 @@ class StepConvertersTest { good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) good( ci.HashMap[String, String]("fish" -> "salmon").keyStepper ) good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.HashSet[String]("salmon").stepper ) + good( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) @@ -224,7 +224,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.HashSet[Double](3.14159).stepper ) + good( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) IFFY( ci.Iterable[Double](3.14159).stepper ) @@ -312,10 +312,10 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) // Int-specific tests - IFFY( co.BitSet(42).stepper ) - IFFY( ci.BitSet(42).stepper ) + good( co.BitSet(42).stepper ) + good( ci.BitSet(42).stepper ) good( ci.NumericRange(123456, 123458, 1).stepper ) - IFFY( cm.BitSet(42).stepper ) + good( cm.BitSet(42).stepper ) good( (1 until 2).stepper ) Okay( ci.IntMap[String](123456 -> "salmon").keyStepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) @@ -346,7 +346,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.HashSet[Int](654321).stepper ) + good( ci.HashSet[Int](654321).stepper ) good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) @@ -468,7 +468,7 @@ class StepConvertersTest { Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.HashSet[Long](0x123456789L).stepper ) + good( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) IFFY( ci.Iterable[Long](0x123456789L).stepper ) From edf0644fb23e4f0348c9f27960b7dcb6d20bb34f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 24 Oct 2015 17:14:59 -0700 Subject: [PATCH 061/340] Added marker trait to indicate when splits are efficient. --- .../scala/compat/java8/StepConverters.scala | 289 +++++++++++------- .../scala/compat/java8/StreamConverters.scala | 18 +- .../compat/java8/collectionImpl/Stepper.scala | 6 + .../collectionImpl/StepsLikeGapped.scala | 10 +- .../collectionImpl/StepsLikeIndexed.scala | 4 + .../collectionImpl/StepsLikeSliced.scala | 4 + 6 files changed, 213 insertions(+), 118 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index ef39d0c..7117628 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -7,6 +7,54 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ + + trait MakesAnyStepper[A] extends Any { + def stepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesAnyKeyStepper[A] extends Any { + def keyStepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesAnyValueStepper[A] extends Any { + def valueStepper: AnyStepper[A] with EfficientSubstep + } + + trait MakesDoubleStepper extends Any { + def stepper: DoubleStepper with EfficientSubstep + } + + trait MakesDoubleKeyStepper extends Any { + def keyStepper: DoubleStepper with EfficientSubstep + } + + trait MakesDoubleValueStepper extends Any { + def valueStepper: DoubleStepper with EfficientSubstep + } + + trait MakesIntStepper extends Any { + def stepper: IntStepper with EfficientSubstep + } + + trait MakesIntKeyStepper extends Any { + def keyStepper: IntStepper with EfficientSubstep + } + + trait MakesIntValueStepper extends Any { + def valueStepper: IntStepper with EfficientSubstep + } + + trait MakesLongStepper extends Any { + def stepper: LongStepper with EfficientSubstep + } + + trait MakesLongKeyStepper extends Any { + def keyStepper: LongStepper with EfficientSubstep + } + + trait MakesLongValueStepper extends Any { + def valueStepper: LongStepper with EfficientSubstep + } private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { @@ -605,52 +653,52 @@ package converterImpls { def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE } - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyArray[A](underlying, 0, underlying.length) + final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) } - final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal{ - @inline def stepper: AnyStepper[A] = new StepsObjectArray[A](underlying, 0, underlying.length) + final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) } - final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal{ - @inline def stepper: AnyStepper[Unit] = new StepsUnitArray(underlying, 0, underlying.length) + final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { + @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) } - final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal{ - @inline def stepper: AnyStepper[Boolean] = new StepsBoxedBooleanArray(underlying, 0, underlying.length) + final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { + @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } - final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal{ - @inline def stepper: AnyStepper[Byte] = new StepsBoxedByteArray(underlying, 0, underlying.length) + final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { + @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) } - final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal { - @inline def stepper: AnyStepper[Char] = new StepsBoxedCharArray(underlying, 0, underlying.length) + final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { + @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) } - final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal{ - @inline def stepper: AnyStepper[Short] = new StepsBoxedShortArray(underlying, 0, underlying.length) + final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { + @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) } - final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal { - @inline def stepper: AnyStepper[Float] = new StepsBoxedFloatArray(underlying, 0, underlying.length) + final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { + @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) } - final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) + final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) } - final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) + final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) + final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) + final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { @@ -685,176 +733,191 @@ package converterImpls { @inline def stepper: LongStepper = new StepsLongIterator(underlying) } - final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal { - @inline def stepper: AnyStepper[T] = new StepsAnyNumericRange[T](underlying, 0, underlying.length) + final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { + @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } - final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyVector[A](underlying, 0, underlying.length) + final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) } - final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = { + final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsAnyFlatHashTable(tbl, 0, tbl.length) } } - final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = { + final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsDoubleFlatHashTable(tbl, 0, tbl.length) } } - final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal { - @inline def stepper: IntStepper = { + final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsIntFlatHashTable(tbl, 0, tbl.length) } } - final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal { - @inline def stepper: LongStepper = { + final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable(underlying) new StepsLongFlatHashTable(tbl, 0, tbl.length) } } - final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) extends AnyVal { - @inline def keyStepper: AnyStepper[K] = { + final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) + extends AnyVal with MakesAnyKeyStepper[K] { + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) new StepsAnyHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) extends AnyVal { - @inline def keyStepper: DoubleStepper = { + final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) + extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) new StepsDoubleHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) extends AnyVal { - @inline def keyStepper: IntStepper = { + final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) + extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) new StepsIntHashTableKey(tbl, 0, tbl.length) } } - final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) extends AnyVal { - @inline def keyStepper: LongStepper = { + final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) + extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) new StepsLongHashTableKey(tbl, 0, tbl.length) } } - final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { - @inline def stepper: AnyStepper[(K,V)] = { + final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) + extends AnyVal with MakesAnyStepper[(K, V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTable(tbl, 0, tbl.length) } } - final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal { - @inline def valueStepper: AnyStepper[V] = { + final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) + extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) extends AnyVal { - @inline def valueStepper: DoubleStepper = { + final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) + extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) extends AnyVal { - @inline def valueStepper: IntStepper = { + final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) + extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) extends AnyVal { - @inline def valueStepper: LongStepper = { + final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) + extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { - @inline def stepper: AnyStepper[(K,V)] = { + final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) + extends AnyVal with MakesAnyStepper[(K,V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTable(tbl, 0, tbl.length) } } - final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal { - @inline def valueStepper: AnyStepper[V] = { + final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) + extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) extends AnyVal { - @inline def valueStepper: DoubleStepper = { + final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) + extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) extends AnyVal { - @inline def valueStepper: IntStepper = { + final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) + extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) extends AnyVal { - @inline def valueStepper: LongStepper = { + final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) + extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) } } - final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal { - @inline def stepper: AnyStepper[(K, V)] = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) - @inline def keyStepper: AnyStepper[K] = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) - @inline def valueStepper: AnyStepper[V] = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) + extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { + @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) } - final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal { - @inline def keyStepper: DoubleStepper = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal { - @inline def valueStepper: DoubleStepper = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal { - @inline def keyStepper: IntStepper = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal { - @inline def valueStepper: IntStepper = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal { - @inline def keyStepper: LongStepper = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) + final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) } - final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal { - @inline def valueStepper: LongStepper = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) + final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) } - final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal { - @inline def stepper: AnyStepper[A] = new StepsAnyImmHashSet(underlying.iterator, underlying.size) + final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) } - final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal { - def stepper: IntStepper = { + final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { + def stepper: IntStepper with EfficientSubstep = { val bits: Array[Long] = underlying match { case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) @@ -868,7 +931,7 @@ package converterImpls { def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper { + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { def characteristics() = NonNull def estimateSize = iN - i0 def hasNext = i0 < iN @@ -1060,55 +1123,55 @@ object StepConverters extends converterImpls.Priority2StepConverters { import converterImpls._ import Stepper._ - implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleArray(underlying, 0, underlying.length) + implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) } - implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntArray(underlying, 0, underlying.length) + implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) } - implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongArray(underlying, 0, underlying.length) + implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) } - implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleVector(underlying, 0, underlying.length) + implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) } - implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntNumericRange(underlying, 0, underlying.length) + implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) } - implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongNumericRange(underlying, 0, underlying.length) - } - - implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntRange(underlying, 0, underlying.length) + implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) } - implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntVector(underlying, 0, underlying.length) + implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + } + + implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) } - implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongVector(underlying, 0, underlying.length) + implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) } - implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal { - @inline def stepper: DoubleStepper = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) } - implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal { - @inline def stepper: IntStepper = new StepsIntImmHashSet(underlying.iterator, underlying.size) + implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) } - implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal { - @inline def stepper: LongStepper = new StepsLongImmHashSet(underlying.iterator, underlying.size) + implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) } - implicit class RichStringCanStep(val underlying: String) extends AnyVal { - @inline def stepper: IntStepper = new StepperStringCodePoint(underlying, 0, underlying.length) + implicit class RichStringCanStep(val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index d45a205..cf07193 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -4,6 +4,7 @@ import language.implicitConversions import java.util.stream._ import scala.compat.java8.collectionImpl._ +import scala.compat.java8.converterImpls._ trait PrimitiveStreamAccumulator[S, AA] { def streamAccumulate(stream: S): AA @@ -13,7 +14,7 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority3StreamConverters { +trait Priority6StreamConverters { implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] @@ -27,7 +28,7 @@ trait Priority3StreamConverters { } } -trait Priority2StreamConverters extends Priority3StreamConverters { +trait Priority5StreamConverters extends Priority6StreamConverters { implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { if (t.isTraversableAgain && t.hasDefiniteSize) { @@ -43,8 +44,21 @@ trait Priority2StreamConverters extends Priority3StreamConverters { java.util.Arrays.stream(mkArr()) def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel + } +} + +trait Priority4StreamConverters extends Priority5StreamConverters { + implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { + def seqStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, false) + def parStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, true) } +} +trait Priority3StreamConverters extends Priority4StreamConverters { + +} + +trait Priority2StreamConverters extends Priority3StreamConverters { implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { private def mkAcc() = { val acc = new Accumulator[A] diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index af5c22a..0295d77 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -38,6 +38,12 @@ import java.util.Spliterator */ trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} +/** An (optional) marker trait that indicates that a `Stepper` can call `substep` with + * at worst O(log N) time and space complexity, and that the division is likely to + * be reasonably even. + */ +trait EfficientSubstep {} + /** Provides functionality for Stepper while keeping track of a more precise type of the collection. */ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala index 87bb295..ab8f2e1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeGapped.scala @@ -35,7 +35,8 @@ abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val u */ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) - with AnyStepper[A] + with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -44,7 +45,8 @@ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underly */ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) - with DoubleStepper + with DoubleStepper + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -53,7 +55,8 @@ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_u */ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) - with IntStepper + with IntStepper + with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -63,4 +66,5 @@ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underly abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) with LongStepper + with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala index b9dfa55..6a55395 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala @@ -24,22 +24,26 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Ints */ abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Longs */ abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper + with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala index a6f2110..d7a1fdb 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala @@ -19,22 +19,26 @@ abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) with DoubleStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) with IntStepper + with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) with LongStepper + with EfficientSubstep {} From 3f02f54749b4c03822198678ec056bfbe606a4da Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 24 Oct 2015 20:59:27 -0700 Subject: [PATCH 062/340] Modified stream converters to mostly defer to StepConverters. --- .../scala/compat/java8/StreamConverters.scala | 171 ++++++------------ .../compat/java8/collectionImpl/Stepper.scala | 3 + .../compat/java8/StreamConvertersTest.scala | 1 + 3 files changed, 56 insertions(+), 119 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index cf07193..d2e3997 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -15,22 +15,24 @@ trait PrimitiveStreamUnboxer[A, S] { } trait Priority6StreamConverters { - implicit class EnrichAnyScalaCollectionWithStream[A](t: TraversableOnce[A]) { + // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. + implicit class EnrichAnyScalaCollectionWithStream[A, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { private def mkAcc() = { val acc = new Accumulator[A] - t.foreach{ acc += _ } + ev(cc).foreach{ acc += _ } acc } def seqStream: Stream[A] = mkAcc().seqStream def parStream: Stream[A] = mkAcc().parStream - } + } } trait Priority5StreamConverters extends Priority6StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef](t: TraversableOnce[A]) { + implicit class EnrichScalaCollectionWithStream[A <: AnyRef, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { + val t = ev(cc) if (t.isTraversableAgain && t.hasDefiniteSize) { val sz = t.size val a = new Array[A](sz) @@ -49,62 +51,62 @@ trait Priority5StreamConverters extends Priority6StreamConverters { trait Priority4StreamConverters extends Priority5StreamConverters { implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { - def seqStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, false) - def parStream: Stream[A] = java.util.stream.StreamSupport.stream(steppize(cc).stepper, true) + def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) + def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichAnyKeySteppableWithStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeyStepper[K]) { + def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) + def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichAnyValueSteppableWithStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueStepper[V]) { + def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) + def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) } } trait Priority3StreamConverters extends Priority4StreamConverters { - -} - -trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichMissingPrimitiveArrayWithStream[A](a: Array[A]) { - private def mkAcc() = { - val acc = new Accumulator[A] - var i = 0 - while (i < a.length) { - acc += a(i) - i += 1 - } - acc - } - - def seqStream: Stream[A] = mkAcc().seqStream - - def parStream: Stream[A] = mkAcc().parStream + implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { + def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) + def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) } -} - -trait Priority1StreamConverters extends Priority2StreamConverters { - implicit class EnrichGenericArrayWithStream[A <: AnyRef](a: Array[A]) { - def seqStream: Stream[A] = java.util.Arrays.stream(a) - def parStream: Stream[A] = seqStream.parallel + implicit class EnrichDoubleKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeyStepper) { + def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) + def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) } - - implicit class EnrichGenericIndexedSeqWithStream[A](c: collection.IndexedSeqLike[A, _]) { - private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyIndexedSeq[A](c, 0, c.length), parallel) - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichDoubleValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueStepper) { + def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) + def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - - implicit class EnrichAnyVectorWithStream[A](c: Vector[A]) { - private def someStream(parallel: Boolean): Stream[A] = - StreamSupport.stream(new converterImpls.StepsAnyVector[A](c, 0, c.length), parallel) - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) { + def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) + def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) } - - implicit class EnrichGenericFlatHashTableWithStream[A](fht: collection.mutable.FlatHashTable[A]) { - private def someStream(parallel: Boolean): Stream[A] = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.stream(new converterImpls.StepsAnyFlatHashTable[A](tbl, 0, tbl.length), parallel) - } - def seqStream: Stream[A] = someStream(false) - def parStream: Stream[A] = someStream(true) + implicit class EnrichIntKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeyStepper) { + def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) + def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichIntValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueStepper) { + def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) + def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) + } + implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) { + def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) + def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichLongKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeyStepper) { + def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) + def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) } + implicit class EnrichLongValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueStepper) { + def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) + def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) + } +} +trait Priority2StreamConverters extends Priority3StreamConverters { +} + +trait Priority1StreamConverters extends Priority2StreamConverters { implicit class RichStream[A](stream: Stream[A]) { def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) @@ -161,75 +163,6 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * ``` */ object StreamConverters extends Priority1StreamConverters { - implicit class EnrichDoubleIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Double, _]](c: CC) { - private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Int, _]](c: CC) { - private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongIndexedSeqWithStream[CC <: collection.IndexedSeqLike[Long, _]](c: CC) { - private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongIndexedSeq[CC](c, 0, c.length), parallel) - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - - implicit class EnrichDoubleVectorWithStream(c: Vector[Double]) { - private def someStream(parallel: Boolean): DoubleStream = - StreamSupport.doubleStream(new converterImpls.StepsDoubleVector(c, 0, c.length), parallel) - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntVectorWithStream(c: Vector[Int]) { - private def someStream(parallel: Boolean): IntStream = - StreamSupport.intStream(new converterImpls.StepsIntVector(c, 0, c.length), parallel) - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongVectorWithStream(c: Vector[Long]) { - private def someStream(parallel: Boolean): LongStream = - StreamSupport.longStream(new converterImpls.StepsLongVector(c, 0, c.length), parallel) - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - - implicit class EnrichDoubleFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Double]) { - private def someStream(parallel: Boolean): DoubleStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.doubleStream(new converterImpls.StepsDoubleFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: DoubleStream = someStream(false) - def parStream: DoubleStream = someStream(true) - } - - implicit class EnrichIntFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Int]) { - private def someStream(parallel: Boolean): IntStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.intStream(new converterImpls.StepsIntFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: IntStream = someStream(false) - def parStream: IntStream = someStream(true) - } - - implicit class EnrichLongFlatHashTableWithStream(fht: collection.mutable.FlatHashTable[Long]) { - private def someStream(parallel: Boolean): LongStream = { - val tbl = runtime.CollectionInternals.getTable(fht) - StreamSupport.longStream(new converterImpls.StepsLongFlatHashTable(tbl, 0, tbl.length), parallel) - } - def seqStream: LongStream = someStream(false) - def parStream: LongStream = someStream(true) - } - implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 0295d77..ddacdd3 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -85,6 +85,9 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => /** Returns the precise underlying type of this `Stepper`. */ def typedPrecisely: CC + + /** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */ + def anticipateParallelism: this.type = this //// diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 9a5b7f9..5799712 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -6,6 +6,7 @@ import org.junit.Assert._ class StreamConvertersTest { import java.util.stream._ import StreamConverters._ + import StepConverters._ def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } From ace87d433aa41aa7d6e74540bb80451d99c5d64c Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 25 Oct 2015 20:56:25 -0700 Subject: [PATCH 063/340] Finished transition to only allowing parStream on Steppers that support it well. Not tested. --- .../scala/compat/java8/StepConverters.scala | 294 +++++++++++++----- .../scala/compat/java8/StreamConverters.scala | 71 +++-- .../compat/java8/StepConvertersTest.scala | 12 +- 3 files changed, 260 insertions(+), 117 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 7117628..9a93367 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,6 +8,54 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ + trait MakesAnySeqStepper[A] extends Any { + def stepper: AnyStepper[A] + } + + trait MakesAnyKeySeqStepper[A] extends Any { + def keyStepper: AnyStepper[A] + } + + trait MakesAnyValueSeqStepper[A] extends Any { + def valueStepper: AnyStepper[A] + } + + trait MakesDoubleSeqStepper extends Any { + def stepper: DoubleStepper + } + + trait MakesDoubleKeySeqStepper extends Any { + def keyStepper: DoubleStepper + } + + trait MakesDoubleValueSeqStepper extends Any { + def valueStepper: DoubleStepper + } + + trait MakesIntSeqStepper extends Any { + def stepper: IntStepper + } + + trait MakesIntKeySeqStepper extends Any { + def keyStepper: IntStepper + } + + trait MakesIntValueSeqStepper extends Any { + def valueStepper: IntStepper + } + + trait MakesLongSeqStepper extends Any { + def stepper: LongStepper + } + + trait MakesLongKeySeqStepper extends Any { + def keyStepper: LongStepper + } + + trait MakesLongValueSeqStepper extends Any { + def valueStepper: LongStepper + } + trait MakesAnyStepper[A] extends Any { def stepper: AnyStepper[A] with EfficientSubstep } @@ -701,35 +749,35 @@ package converterImpls { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } - final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal { + final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) } - final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal { + final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) } - final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal { + final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) } - final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal { + final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) } - final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal { + final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) } - final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal { + final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) } - final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal { + final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { @inline def stepper: IntStepper = new StepsIntIterator(underlying) } - final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal { + final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { @inline def stepper: LongStepper = new StepsLongIterator(underlying) } @@ -955,75 +1003,111 @@ package converterImpls { } } - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal { + final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) } - final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal { + final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) } - final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal { + final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) } - final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal { + final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) } - final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal { + final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) } - final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal { + final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) } - final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal { + final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) } - final class RichTraversableOnceCanStep[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def stepper: AnyStepper[A] = { - val acc = new Accumulator[A] - underlying.foreach(acc += _) - acc.stepper - } + final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) } - final class RichDoubleTraversableOnceCanStep(private val underlying: TraversableOnce[Double]) extends AnyVal { - def stepper: DoubleStepper = { - val acc = new DoubleAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) } - final class RichIntTraversableOnceCanStep(private val underlying: TraversableOnce[Int]) extends AnyVal { - def stepper: IntStepper = { - val acc = new IntAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) } - final class RichLongTraversableOnceCanStep(private val underlying: TraversableOnce[Long]) extends AnyVal { - def stepper: LongStepper = { - val acc = new LongAccumulator - underlying.foreach(acc += _) - acc.stepper - } + final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) + } + + final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) + } + + final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) + } + + final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) + } + + final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) + } + + final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) + } + + final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) + } + + final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + } + + final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) + } + + final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) + } + + final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + } + + final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) + } + + final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) } + final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) + } + trait Priority7StepConverters { - implicit def richTraversableOnceCanStep[A](underlying: TraversableOnce[A]) = new RichTraversableOnceCanStep(underlying) + implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) } trait Priority6StepConverters extends Priority7StepConverters { - implicit def richDoubleTraversableOnceCanStep(underlying: TraversableOnce[Double]) = new RichDoubleTraversableOnceCanStep(underlying) - implicit def richIntTraversableOnceCanStep(underlying: TraversableOnce[Int]) = new RichIntTraversableOnceCanStep(underlying) - implicit def richLongTraversableOnceCanStep(underlying: TraversableOnce[Long]) = new RichLongTraversableOnceCanStep(underlying) + implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) + implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) + implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } @@ -1117,61 +1201,109 @@ package converterImpls { implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) } -} -object StepConverters extends converterImpls.Priority2StepConverters { - import converterImpls._ - import Stepper._ + trait Priority1StepConverters extends Priority2StepConverters { + implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) + implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) + implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) + + implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) + implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) + implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - implicit class RichArrayDoubleCanStep(val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) + implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) + implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) + implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) + + implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) + implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) + implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) + + implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } - implicit class RichArrayIntCanStep(val underlying: Array[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) + final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + underlying.foreach(a += _) + a + } } - - implicit class RichArrayLongCanStep(val underlying: Array[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) + + final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) + final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) + final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + underlying.foreach(da += _) + da + } } - - implicit class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) - } - - implicit class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) + final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + var i = 0 + while (i < underlying.length) { a += underlying(i); i += 1 } + a + } } - implicit class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) + final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - - implicit class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) + final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - - implicit class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) + final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } } - implicit class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) + trait Priority3AccumulatorConverters { + implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) } - implicit class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) + trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { + implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) } - implicit class RichStringCanStep(val underlying: String) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) + trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { + implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) } } + +object StepConverters +extends converterImpls.Priority1StepConverters +with converterImpls.Priority1AccumulatorConverters +{} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index d2e3997..60d7114 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -14,42 +14,50 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority6StreamConverters { +trait Priority5StreamConverters { // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. - implicit class EnrichAnyScalaCollectionWithStream[A, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { - private def mkAcc() = { - val acc = new Accumulator[A] - ev(cc).foreach{ acc += _ } - acc - } - - def seqStream: Stream[A] = mkAcc().seqStream - - def parStream: Stream[A] = mkAcc().parStream + implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) { + def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeySeqStepper[K]) { + def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithValueSeqStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueSeqStepper[V]) { + def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) } } -trait Priority5StreamConverters extends Priority6StreamConverters { - implicit class EnrichScalaCollectionWithStream[A <: AnyRef, CC](cc: CC)(implicit ev: CC <:< TraversableOnce[A]) { - private def mkArr()(implicit tag: reflect.ClassTag[A]): Array[A] = { - val t = ev(cc) - if (t.isTraversableAgain && t.hasDefiniteSize) { - val sz = t.size - val a = new Array[A](sz) - t.copyToArray(a, 0, sz) - a - } - else t.toArray[A] - } - - def seqStream(implicit tag: reflect.ClassTag[A]): Stream[A] = - java.util.Arrays.stream(mkArr()) - - def parStream(implicit tag: reflect.ClassTag[A]): Stream[A] = seqStream.parallel +trait Priority4StreamConverters extends Priority5StreamConverters { + implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) { + def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) { + def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) { + def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) + } + implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeySeqStepper) { + def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) } + implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeySeqStepper) { + def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeySeqStepper) { + def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) + } + implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueSeqStepper) { + def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) + } + implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueSeqStepper) { + def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) + } + implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueSeqStepper) { + def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) + } } -trait Priority4StreamConverters extends Priority5StreamConverters { +trait Priority3StreamConverters extends Priority4StreamConverters { implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) @@ -64,7 +72,7 @@ trait Priority4StreamConverters extends Priority5StreamConverters { } } -trait Priority3StreamConverters extends Priority4StreamConverters { +trait Priority2StreamConverters extends Priority3StreamConverters { implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) @@ -103,9 +111,6 @@ trait Priority3StreamConverters extends Priority4StreamConverters { } } -trait Priority2StreamConverters extends Priority3StreamConverters { -} - trait Priority1StreamConverters extends Priority2StreamConverters { implicit class RichStream[A](stream: Stream[A]) { def accumulate = stream.collect(Accumulator.supplier[A], Accumulator.adder[A], Accumulator.merger[A]) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index c227463..d0fb173 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -47,6 +47,12 @@ class StepConvertersTest { assert(isLin(x)) } + def Fine[X](x: => X)(implicit correctSpec: SpecCheck) { + assert(x.isInstanceOf[Stepper[_]]) + assert(correctSpec(x)) + assert(!isAcc(x)) + } + def good[X](x: => X)(implicit correctSpec: SpecCheck) { assert(x.isInstanceOf[Stepper[_]]) assert(correctSpec(x)) @@ -81,9 +87,9 @@ class StepConvertersTest { Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) IFFY( co.SortedSet[String]("salmon").stepper ) - IFFY( co.Traversable[String]("salmon").stepper ) - IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).stepper ) - IFFY( co.Traversable[String]("salmon").view.stepper ) + IFFY( co.Traversable[String]("salmon").accumulate.stepper ) + IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).accumulate.stepper ) + IFFY( co.Traversable[String]("salmon").view.accumulate.stepper ) // Immutable section IFFY( ci.::("salmon", Nil).stepper ) From 72fb53dcf27cc663bcf1aa3baab303bee8faca6b Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 19:28:07 -0800 Subject: [PATCH 064/340] Fixed up tests after disallowing implicit Accumulator creation. --- .../compat/java8/collectionImpl/Stepper.scala | 9 + .../compat/java8/StepConvertersTest.scala | 294 +++++++++--------- .../compat/java8/StreamConvertersTest.scala | 8 +- 3 files changed, 160 insertions(+), 151 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index ddacdd3..730fef8 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -161,6 +161,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => } } + /** This trait indicates that a `Stepper` will implement `tryStep` in terms of `hasNext` and `nextStep`. */ trait NextStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with StepperLike[A, NextStepper[A]] { def tryStep(f: A => Unit) = if (hasStep) { f(nextStep()); true } else false @@ -224,6 +225,8 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def trySplit() = substep.typedPrecisely final def typedPrecisely: AnyStepper[A] = this override def spliterator: Spliterator[A] = this + def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false) + def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true) } /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ @@ -239,6 +242,8 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD def trySplit() = substep.typedPrecisely final def typedPrecisely: DoubleStepper = this override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double + def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false) + def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, true) } /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ @@ -254,6 +259,8 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit def trySplit() = substep.typedPrecisely final def typedPrecisely = this override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int + def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false) + def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, true) } /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ @@ -269,6 +276,8 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong def trySplit() = substep.typedPrecisely final def typedPrecisely = this override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long + def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false) + def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true) } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index d0fb173..c3f1663 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -73,27 +73,27 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[String]("salmon").buffered.stepper ) good( co.IndexedSeq[String]("salmon").stepper ) - IFFY( co.Iterable[String]("salmon").stepper ) - IFFY( co.Iterable[String]("salmon").view.stepper ) + Okay( co.Iterable[String]("salmon").stepper ) + Okay( co.Iterable[String]("salmon").view.stepper ) Okay( co.Iterator[String]("salmon").stepper ) Okay( co.LinearSeq[String]("salmon").stepper ) - IFFY( co.Map[String, String]("fish" -> "salmon").stepper ) + Okay( co.Map[String, String]("fish" -> "salmon").stepper ) Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) - IFFY( co.Seq[String]("salmon").stepper ) - IFFY( co.Seq[String]("salmon").view.stepper ) - IFFY( co.Set[String]("salmon").stepper ) - IFFY( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( co.Seq[String]("salmon").stepper ) + Okay( co.Seq[String]("salmon").view.stepper ) + Okay( co.Set[String]("salmon").stepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").stepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( co.SortedSet[String]("salmon").stepper ) + Okay( co.SortedSet[String]("salmon").stepper ) IFFY( co.Traversable[String]("salmon").accumulate.stepper ) IFFY( (co.Iterator[String]("salmon"): co.TraversableOnce[String]).accumulate.stepper ) IFFY( co.Traversable[String]("salmon").view.accumulate.stepper ) // Immutable section - IFFY( ci.::("salmon", Nil).stepper ) - IFFY( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + Okay( ci.::("salmon", Nil).stepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) good( ci.HashMap[String, String]("fish" -> "salmon").stepper ) @@ -101,46 +101,46 @@ class StepConvertersTest { good( ci.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( ci.HashSet[String]("salmon").stepper ) good( ci.IndexedSeq[String]("salmon").stepper ) - IFFY( ci.IntMap[String](123456 -> "salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").stepper ) Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) - IFFY( ci.Iterable[String]("salmon").stepper ) + Okay( ci.Iterable[String]("salmon").stepper ) Okay( ci.LinearSeq[String]("salmon").stepper ) Okay( ci.List[String]("salmon").stepper ) - IFFY( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.ListSet[String]("salmon").stepper ) - IFFY( ci.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( ci.ListSet[String]("salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").stepper ) Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) - IFFY( ci.Map[String, String]("fish" -> "salmon").stepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").stepper ) Okay( ci.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.Map[String, String]("fish" -> "salmon").valueStepper ) Okay( ci.Queue[String]("salmon").stepper ) - IFFY( ci.Seq[String]("salmon").stepper ) - IFFY( ci.Set[String]("salmon").stepper ) - IFFY( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.Seq[String]("salmon").stepper ) + Okay( ci.Set[String]("salmon").stepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.SortedSet[String]("salmon").stepper ) + Okay( ci.SortedSet[String]("salmon").stepper ) Okay( ci.Stack[String]("salmon").stepper ) Okay( ci.Stream[String]("salmon").stepper ) _eh_( ci.Stream[String]("salmon").view.stepper ) - IFFY( ci.Traversable[String]("salmon").stepper ) - IFFY( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + IFFY( ci.Traversable[String]("salmon").accumulate.stepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( ci.TreeSet[String]("salmon").stepper ) + Okay( ci.TreeSet[String]("salmon").stepper ) good( ci.Vector[String]("salmon").stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) - IFFY( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) - IFFY( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) + Okay( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) - IFFY( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) - IFFY( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) + Okay( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) good( cm.ArrayBuffer[String]("salmon").stepper ) @@ -148,43 +148,43 @@ class StepConvertersTest { good( (Array("salmon"): cm.ArrayOps[String]).stepper ) good( cm.ArraySeq[String]("salmon").stepper ) _eh_( cm.ArrayStack[String]("salmon").stepper ) - IFFY( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) good( cm.HashMap[String, String]("fish" -> "salmon").stepper ) good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) good( cm.HashSet[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").stepper ) good( cm.IndexedSeq[String]("salmon").view.stepper ) - IFFY( cm.Iterable[String]("salmon").stepper ) + Okay( cm.Iterable[String]("salmon").stepper ) Okay( cm.LinearSeq[String]("salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( cm.LinkedHashSet[String]("salmon").stepper ) - IFFY( cm.ListBuffer[String]("salmon").stepper ) - IFFY( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.LinkedHashSet[String]("salmon").stepper ) + Okay( cm.ListBuffer[String]("salmon").stepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) - IFFY( cm.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").stepper ) Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) - IFFY( cm.Map[String, String]("fish" -> "salmon").stepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").stepper ) Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) Okay( cm.MutableList[String]("salmon").stepper ) - IFFY( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) - IFFY( cm.PriorityQueue[String]("salmon").stepper ) + Okay( cm.PriorityQueue[String]("salmon").stepper ) Okay( cm.Queue[String]("salmon").stepper ) good( cm.ResizableArray[String]("salmon").stepper ) - IFFY( cm.Seq[String]("salmon").stepper ) - IFFY( cm.Set[String]("salmon").stepper ) - IFFY( cm.SortedSet[String]("salmon").stepper ) - IFFY( cm.Stack[String]("salmon").stepper ) - IFFY( cm.Traversable[String]("salmon").stepper ) - IFFY( cm.TreeSet[String]("salmon").stepper ) - IFFY( cm.UnrolledBuffer[String]("salmon").stepper ) - IFFY( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.Seq[String]("salmon").stepper ) + Okay( cm.Set[String]("salmon").stepper ) + Okay( cm.SortedSet[String]("salmon").stepper ) + Okay( cm.Stack[String]("salmon").stepper ) + IFFY( cm.Traversable[String]("salmon").accumulate.stepper ) + Okay( cm.TreeSet[String]("salmon").stepper ) + Okay( cm.UnrolledBuffer[String]("salmon").stepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) good( (Array("salmon"): cm.WrappedArray[String]).stepper ) @@ -192,10 +192,10 @@ class StepConvertersTest { // Java 6 converters section // Concurrent section - IFFY( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) - IFFY( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).keyStepper ) Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).valueStepper ) } @@ -208,24 +208,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Double](3.14159).buffered.stepper ) good( co.IndexedSeq[Double](3.14159).stepper ) - IFFY( co.Iterable[Double](3.14159).stepper ) - IFFY( co.Iterable[Double](3.14159).view.stepper ) + Okay( co.Iterable[Double](3.14159).stepper ) + Okay( co.Iterable[Double](3.14159).view.stepper ) Okay( co.Iterator[Double](3.14159).stepper ) Okay( co.LinearSeq[Double](3.14159).stepper ) Okay( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( co.Seq[Double](3.14159).stepper ) - IFFY( co.Seq[Double](3.14159).view.stepper ) - IFFY( co.Set[Double](3.14159).stepper ) + Okay( co.Seq[Double](3.14159).stepper ) + Okay( co.Seq[Double](3.14159).view.stepper ) + Okay( co.Set[Double](3.14159).stepper ) Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( co.SortedSet[Double](3.14159).stepper ) - IFFY( co.Traversable[Double](3.14159).stepper ) - IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).stepper ) - IFFY( co.Traversable[Double](3.14159).view.stepper ) + Okay( co.SortedSet[Double](3.14159).stepper ) + IFFY( co.Traversable[Double](3.14159).accumulate.stepper ) + IFFY( (co.Iterator[Double](3.14159): co.TraversableOnce[Double]).accumulate.stepper ) + IFFY( co.Traversable[Double](3.14159).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(3.14159, Nil).stepper ) + Okay( ci.::(3.14159, Nil).stepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) good( ci.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) @@ -233,55 +233,55 @@ class StepConvertersTest { good( ci.HashSet[Double](3.14159).stepper ) good( ci.IndexedSeq[Double](3.14159).stepper ) Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) - IFFY( ci.Iterable[Double](3.14159).stepper ) + Okay( ci.Iterable[Double](3.14159).stepper ) Okay( ci.LinearSeq[Double](3.14159).stepper ) Okay( ci.List[Double](3.14159).stepper ) Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.ListSet[Double](3.14159).stepper ) + Okay( ci.ListSet[Double](3.14159).stepper ) Okay( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( ci.Queue[Double](3.14159).stepper ) - IFFY( ci.Seq[Double](3.14159).stepper ) - IFFY( ci.Set[Double](3.14159).stepper ) + Okay( ci.Seq[Double](3.14159).stepper ) + Okay( ci.Set[Double](3.14159).stepper ) Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.SortedSet[Double](3.14159).stepper ) + Okay( ci.SortedSet[Double](3.14159).stepper ) Okay( ci.Stack[Double](3.14159).stepper ) Okay( ci.Stream[Double](3.14159).stepper ) _eh_( ci.Stream[Double](3.14159).view.stepper ) - IFFY( ci.Traversable[Double](3.14159).stepper ) + IFFY( ci.Traversable[Double](3.14159).accumulate.stepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( ci.TreeSet[Double](3.14159).stepper ) + Okay( ci.TreeSet[Double](3.14159).stepper ) good( ci.Vector[Double](3.14159).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) - IFFY( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) + Okay( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) - IFFY( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) + Okay( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) good( cm.ArrayBuffer[Double](3.14159).stepper ) good( ((Array(3.14159): cm.WrappedArray[Double]): cm.ArrayLike[Double, cm.WrappedArray[Double]]).stepper ) good( (Array(3.14159): cm.ArrayOps[Double]).stepper ) good( cm.ArraySeq[Double](3.14159).stepper ) _eh_( cm.ArrayStack[Double](3.14159).stepper ) - IFFY( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( cm.HashSet[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).stepper ) good( cm.IndexedSeq[Double](3.14159).view.stepper ) - IFFY( cm.Iterable[Double](3.14159).stepper ) + Okay( cm.Iterable[Double](3.14159).stepper ) Okay( cm.LinearSeq[Double](3.14159).stepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( cm.LinkedHashSet[Double](3.14159).stepper ) - IFFY( cm.ListBuffer[Double](3.14159).stepper ) + Okay( cm.LinkedHashSet[Double](3.14159).stepper ) + Okay( cm.ListBuffer[Double](3.14159).stepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) @@ -290,16 +290,16 @@ class StepConvertersTest { Okay( cm.MutableList[Double](3.14159).stepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) - IFFY( cm.PriorityQueue[Double](3.14159).stepper ) + Okay( cm.PriorityQueue[Double](3.14159).stepper ) Okay( cm.Queue[Double](3.14159).stepper ) good( cm.ResizableArray[Double](3.14159).stepper ) - IFFY( cm.Seq[Double](3.14159).stepper ) - IFFY( cm.Set[Double](3.14159).stepper ) - IFFY( cm.SortedSet[Double](3.14159).stepper ) - IFFY( cm.Stack[Double](3.14159).stepper ) - IFFY( cm.Traversable[Double](3.14159).stepper ) - IFFY( cm.TreeSet[Double](3.14159).stepper ) - IFFY( cm.UnrolledBuffer[Double](3.14159).stepper ) + Okay( cm.Seq[Double](3.14159).stepper ) + Okay( cm.Set[Double](3.14159).stepper ) + Okay( cm.SortedSet[Double](3.14159).stepper ) + Okay( cm.Stack[Double](3.14159).stepper ) + IFFY( cm.Traversable[Double](3.14159).accumulate.stepper ) + Okay( cm.TreeSet[Double](3.14159).stepper ) + Okay( cm.UnrolledBuffer[Double](3.14159).stepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) good( (Array(3.14159): cm.WrappedArray[Double]).stepper ) @@ -330,24 +330,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Int](654321).buffered.stepper ) good( co.IndexedSeq[Int](654321).stepper ) - IFFY( co.Iterable[Int](654321).stepper ) - IFFY( co.Iterable[Int](654321).view.stepper ) + Okay( co.Iterable[Int](654321).stepper ) + Okay( co.Iterable[Int](654321).view.stepper ) Okay( co.Iterator[Int](654321).stepper ) Okay( co.LinearSeq[Int](654321).stepper ) Okay( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( co.Seq[Int](654321).stepper ) - IFFY( co.Seq[Int](654321).view.stepper ) - IFFY( co.Set[Int](654321).stepper ) + Okay( co.Seq[Int](654321).stepper ) + Okay( co.Seq[Int](654321).view.stepper ) + Okay( co.Set[Int](654321).stepper ) Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( co.SortedSet[Int](654321).stepper ) - IFFY( co.Traversable[Int](654321).stepper ) - IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).stepper ) - IFFY( co.Traversable[Int](654321).view.stepper ) + Okay( co.SortedSet[Int](654321).stepper ) + IFFY( co.Traversable[Int](654321).accumulate.stepper ) + IFFY( (co.Iterator[Int](654321): co.TraversableOnce[Int]).accumulate.stepper ) + IFFY( co.Traversable[Int](654321).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(654321, Nil).stepper ) + Okay( ci.::(654321, Nil).stepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) good( ci.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) @@ -356,55 +356,55 @@ class StepConvertersTest { good( ci.IndexedSeq[Int](654321).stepper ) Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) - IFFY( ci.Iterable[Int](654321).stepper ) + Okay( ci.Iterable[Int](654321).stepper ) Okay( ci.LinearSeq[Int](654321).stepper ) Okay( ci.List[Int](654321).stepper ) Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.ListSet[Int](654321).stepper ) + Okay( ci.ListSet[Int](654321).stepper ) Okay( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) Okay( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( ci.Queue[Int](654321).stepper ) - IFFY( ci.Seq[Int](654321).stepper ) - IFFY( ci.Set[Int](654321).stepper ) + Okay( ci.Seq[Int](654321).stepper ) + Okay( ci.Set[Int](654321).stepper ) Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.SortedSet[Int](654321).stepper ) + Okay( ci.SortedSet[Int](654321).stepper ) Okay( ci.Stack[Int](654321).stepper ) Okay( ci.Stream[Int](654321).stepper ) _eh_( ci.Stream[Int](654321).view.stepper ) - IFFY( ci.Traversable[Int](654321).stepper ) + IFFY( ci.Traversable[Int](654321).accumulate.stepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( ci.TreeSet[Int](654321).stepper ) + Okay( ci.TreeSet[Int](654321).stepper ) good( ci.Vector[Int](654321).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) - IFFY( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) + Okay( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) - IFFY( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) - IFFY( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) + Okay( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) good( cm.ArrayBuffer[Int](654321).stepper ) good( ((Array(654321): cm.WrappedArray[Int]): cm.ArrayLike[Int, cm.WrappedArray[Int]]).stepper ) good( (Array(654321): cm.ArrayOps[Int]).stepper ) good( cm.ArraySeq[Int](654321).stepper ) _eh_( cm.ArrayStack[Int](654321).stepper ) - IFFY( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( cm.HashSet[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).stepper ) good( cm.IndexedSeq[Int](654321).view.stepper ) - IFFY( cm.Iterable[Int](654321).stepper ) + Okay( cm.Iterable[Int](654321).stepper ) Okay( cm.LinearSeq[Int](654321).stepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( cm.LinkedHashSet[Int](654321).stepper ) - IFFY( cm.ListBuffer[Int](654321).stepper ) + Okay( cm.LinkedHashSet[Int](654321).stepper ) + Okay( cm.ListBuffer[Int](654321).stepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) @@ -413,16 +413,16 @@ class StepConvertersTest { Okay( cm.MutableList[Int](654321).stepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) - IFFY( cm.PriorityQueue[Int](654321).stepper ) + Okay( cm.PriorityQueue[Int](654321).stepper ) Okay( cm.Queue[Int](654321).stepper ) good( cm.ResizableArray[Int](654321).stepper ) - IFFY( cm.Seq[Int](654321).stepper ) - IFFY( cm.Set[Int](654321).stepper ) - IFFY( cm.SortedSet[Int](654321).stepper ) - IFFY( cm.Stack[Int](654321).stepper ) - IFFY( cm.Traversable[Int](654321).stepper ) - IFFY( cm.TreeSet[Int](654321).stepper ) - IFFY( cm.UnrolledBuffer[Int](654321).stepper ) + Okay( cm.Seq[Int](654321).stepper ) + Okay( cm.Set[Int](654321).stepper ) + Okay( cm.SortedSet[Int](654321).stepper ) + Okay( cm.Stack[Int](654321).stepper ) + IFFY( cm.Traversable[Int](654321).accumulate.stepper ) + Okay( cm.TreeSet[Int](654321).stepper ) + Okay( cm.UnrolledBuffer[Int](654321).stepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) good( (Array(654321): cm.WrappedArray[Int]).stepper ) @@ -452,24 +452,24 @@ class StepConvertersTest { // Collection section Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) good( co.IndexedSeq[Long](0x123456789L).stepper ) - IFFY( co.Iterable[Long](0x123456789L).stepper ) - IFFY( co.Iterable[Long](0x123456789L).view.stepper ) + Okay( co.Iterable[Long](0x123456789L).stepper ) + Okay( co.Iterable[Long](0x123456789L).view.stepper ) Okay( co.Iterator[Long](0x123456789L).stepper ) Okay( co.LinearSeq[Long](0x123456789L).stepper ) Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( co.Seq[Long](0x123456789L).stepper ) - IFFY( co.Seq[Long](0x123456789L).view.stepper ) - IFFY( co.Set[Long](0x123456789L).stepper ) + Okay( co.Seq[Long](0x123456789L).stepper ) + Okay( co.Seq[Long](0x123456789L).view.stepper ) + Okay( co.Set[Long](0x123456789L).stepper ) Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( co.SortedSet[Long](0x123456789L).stepper ) - IFFY( co.Traversable[Long](0x123456789L).stepper ) - IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).stepper ) - IFFY( co.Traversable[Long](0x123456789L).view.stepper ) + Okay( co.SortedSet[Long](0x123456789L).stepper ) + IFFY( co.Traversable[Long](0x123456789L).accumulate.stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.TraversableOnce[Long]).accumulate.stepper ) + IFFY( co.Traversable[Long](0x123456789L).view.accumulate.stepper ) // Immutable section - IFFY( ci.::(0x123456789L, Nil).stepper ) + Okay( ci.::(0x123456789L, Nil).stepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) good( ci.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) @@ -477,56 +477,56 @@ class StepConvertersTest { good( ci.HashSet[Long](0x123456789L).stepper ) good( ci.IndexedSeq[Long](0x123456789L).stepper ) Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) - IFFY( ci.Iterable[Long](0x123456789L).stepper ) + Okay( ci.Iterable[Long](0x123456789L).stepper ) Okay( ci.LinearSeq[Long](0x123456789L).stepper ) Okay( ci.List[Long](0x123456789L).stepper ) Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.ListSet[Long](0x123456789L).stepper ) + Okay( ci.ListSet[Long](0x123456789L).stepper ) Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( ci.Queue[Long](0x123456789L).stepper ) - IFFY( ci.Seq[Long](0x123456789L).stepper ) - IFFY( ci.Set[Long](0x123456789L).stepper ) + Okay( ci.Seq[Long](0x123456789L).stepper ) + Okay( ci.Set[Long](0x123456789L).stepper ) Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.SortedSet[Long](0x123456789L).stepper ) + Okay( ci.SortedSet[Long](0x123456789L).stepper ) Okay( ci.Stack[Long](0x123456789L).stepper ) Okay( ci.Stream[Long](0x123456789L).stepper ) _eh_( ci.Stream[Long](0x123456789L).view.stepper ) - IFFY( ci.Traversable[Long](0x123456789L).stepper ) + IFFY( ci.Traversable[Long](0x123456789L).accumulate.stepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( ci.TreeSet[Long](0x123456789L).stepper ) + Okay( ci.TreeSet[Long](0x123456789L).stepper ) good( ci.Vector[Long](0x123456789L).stepper ) // Mutable section - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) - IFFY( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) + Okay( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) - IFFY( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) + Okay( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) good( cm.ArrayBuffer[Long](0x123456789L).stepper ) good( ((Array(0x123456789L): cm.WrappedArray[Long]): cm.ArrayLike[Long, cm.WrappedArray[Long]]).stepper ) good( (Array(0x123456789L): cm.ArrayOps[Long]).stepper ) good( cm.ArraySeq[Long](0x123456789L).stepper ) _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) - IFFY( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( cm.HashSet[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).stepper ) good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) - IFFY( cm.Iterable[Long](0x123456789L).stepper ) + Okay( cm.Iterable[Long](0x123456789L).stepper ) Okay( cm.LinearSeq[Long](0x123456789L).stepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( cm.LinkedHashSet[Long](0x123456789L).stepper ) - IFFY( cm.ListBuffer[Long](0x123456789L).stepper ) + Okay( cm.LinkedHashSet[Long](0x123456789L).stepper ) + Okay( cm.ListBuffer[Long](0x123456789L).stepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) @@ -536,16 +536,16 @@ class StepConvertersTest { Okay( cm.MutableList[Long](0x123456789L).stepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) - IFFY( cm.PriorityQueue[Long](0x123456789L).stepper ) + Okay( cm.PriorityQueue[Long](0x123456789L).stepper ) Okay( cm.Queue[Long](0x123456789L).stepper ) good( cm.ResizableArray[Long](0x123456789L).stepper ) - IFFY( cm.Seq[Long](0x123456789L).stepper ) - IFFY( cm.Set[Long](0x123456789L).stepper ) - IFFY( cm.SortedSet[Long](0x123456789L).stepper ) - IFFY( cm.Stack[Long](0x123456789L).stepper ) - IFFY( cm.Traversable[Long](0x123456789L).stepper ) - IFFY( cm.TreeSet[Long](0x123456789L).stepper ) - IFFY( cm.UnrolledBuffer[Long](0x123456789L).stepper ) + Okay( cm.Seq[Long](0x123456789L).stepper ) + Okay( cm.Set[Long](0x123456789L).stepper ) + Okay( cm.SortedSet[Long](0x123456789L).stepper ) + Okay( cm.Stack[Long](0x123456789L).stepper ) + IFFY( cm.Traversable[Long](0x123456789L).accumulate.stepper ) + Okay( cm.TreeSet[Long](0x123456789L).stepper ) + Okay( cm.UnrolledBuffer[Long](0x123456789L).stepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) good( (Array(0x123456789L): cm.WrappedArray[Long]).stepper ) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 5799712..6a452ec 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -135,7 +135,7 @@ class StreamConvertersTest { val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) - assertEq(seqO, seqO.parStream.toScala[Seq]) + //assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) @@ -154,7 +154,7 @@ class StreamConvertersTest { val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) - assertEq(seqD, seqD.parStream.toScala[Seq]) + //assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) @@ -183,7 +183,7 @@ class StreamConvertersTest { val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) - assertEq(seqI, seqI.parStream.toScala[Seq]) + //assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) @@ -212,7 +212,7 @@ class StreamConvertersTest { val vecL = vectL(n) val hsL = hsetL(n) assertEq(seqL, seqL.seqStream.toScala[Seq]) - assertEq(seqL, seqL.parStream.toScala[Seq]) + //assertEq(seqL, seqL.stepper.parStream.toScala[Seq]) assertEq(seqL, arrL.seqStream.toScala[Seq]) assertEq(seqL, arrL.parStream.toScala[Seq]) assert(arrL.seqStream.isInstanceOf[LongStream]) From 675f2edc11c02388d5fecad53f6416f1bb77674a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:20:33 -0800 Subject: [PATCH 065/340] Factored out MakeXyzStepper traits into `MakesSteppers`. --- .../scala/compat/java8/StepConverters.scala | 96 ----------- .../java8/collectionImpl/MakesSteppers.scala | 150 ++++++++++++++++++ .../compat/java8/collectionImpl/Stepper.scala | 8 +- .../compat/java8/StreamConvertersTest.scala | 6 +- 4 files changed, 157 insertions(+), 103 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 9a93367..d88e34c 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,102 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - trait MakesAnySeqStepper[A] extends Any { - def stepper: AnyStepper[A] - } - - trait MakesAnyKeySeqStepper[A] extends Any { - def keyStepper: AnyStepper[A] - } - - trait MakesAnyValueSeqStepper[A] extends Any { - def valueStepper: AnyStepper[A] - } - - trait MakesDoubleSeqStepper extends Any { - def stepper: DoubleStepper - } - - trait MakesDoubleKeySeqStepper extends Any { - def keyStepper: DoubleStepper - } - - trait MakesDoubleValueSeqStepper extends Any { - def valueStepper: DoubleStepper - } - - trait MakesIntSeqStepper extends Any { - def stepper: IntStepper - } - - trait MakesIntKeySeqStepper extends Any { - def keyStepper: IntStepper - } - - trait MakesIntValueSeqStepper extends Any { - def valueStepper: IntStepper - } - - trait MakesLongSeqStepper extends Any { - def stepper: LongStepper - } - - trait MakesLongKeySeqStepper extends Any { - def keyStepper: LongStepper - } - - trait MakesLongValueSeqStepper extends Any { - def valueStepper: LongStepper - } - - trait MakesAnyStepper[A] extends Any { - def stepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesAnyKeyStepper[A] extends Any { - def keyStepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesAnyValueStepper[A] extends Any { - def valueStepper: AnyStepper[A] with EfficientSubstep - } - - trait MakesDoubleStepper extends Any { - def stepper: DoubleStepper with EfficientSubstep - } - - trait MakesDoubleKeyStepper extends Any { - def keyStepper: DoubleStepper with EfficientSubstep - } - - trait MakesDoubleValueStepper extends Any { - def valueStepper: DoubleStepper with EfficientSubstep - } - - trait MakesIntStepper extends Any { - def stepper: IntStepper with EfficientSubstep - } - - trait MakesIntKeyStepper extends Any { - def keyStepper: IntStepper with EfficientSubstep - } - - trait MakesIntValueStepper extends Any { - def valueStepper: IntStepper with EfficientSubstep - } - - trait MakesLongStepper extends Any { - def stepper: LongStepper with EfficientSubstep - } - - trait MakesLongKeyStepper extends Any { - def keyStepper: LongStepper with EfficientSubstep - } - - trait MakesLongValueStepper extends Any { - def valueStepper: LongStepper with EfficientSubstep - } - private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE diff --git a/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala new file mode 100644 index 0000000..8a78541 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/MakesSteppers.scala @@ -0,0 +1,150 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +/** Classes or objects implementing this trait create generic steppers suitable for sequential use. */ +trait MakesAnySeqStepper[A] extends Any { + /** Generates a fresh stepper over `A`s suitable for sequential use */ + def stepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential use. */ +trait MakesAnyKeySeqStepper[A] extends Any { + /** Generates a fresh stepper over map keys of type `A` suitable for sequential use */ + def keyStepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential use. */ +trait MakesAnyValueSeqStepper[A] extends Any { + /** Generates a fresh stepper over map values of type `A` suitable for sequential use */ + def valueStepper: AnyStepper[A] +} + +/** Classes or objects implementing this trait create `Double` steppers suitable for sequential use. */ +trait MakesDoubleSeqStepper extends Any { + /** Generates a fresh stepper over `Double`s suitable for sequential use */ + def stepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential use. */ +trait MakesDoubleKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Double` suitable for sequential use */ + def keyStepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential use. */ +trait MakesDoubleValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Double` suitable for sequential use */ + def valueStepper: DoubleStepper +} + +/** Classes or objects implementing this trait create `Int` steppers suitable for sequential use. */ +trait MakesIntSeqStepper extends Any { + /** Generates a fresh stepper over `Int`s suitable for sequential use */ + def stepper: IntStepper +} + +/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential use. */ +trait MakesIntKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Int` suitable for sequential use */ + def keyStepper: IntStepper +} + +/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential use. */ +trait MakesIntValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Int` suitable for sequential use */ + def valueStepper: IntStepper +} + +/** Classes or objects implementing this trait create `Long` steppers suitable for sequential use. */ +trait MakesLongSeqStepper extends Any { + /** Generates a fresh stepper over `Long`s suitable for sequential use */ + def stepper: LongStepper +} + +/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential use. */ +trait MakesLongKeySeqStepper extends Any { + /** Generates a fresh stepper over map keys of type `Long` suitable for sequential use */ + def keyStepper: LongStepper +} + +/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential use. */ +trait MakesLongValueSeqStepper extends Any { + /** Generates a fresh stepper over map values of type `Long` suitable for sequential use */ + def valueStepper: LongStepper +} + +/** Classes or objects implementing this trait create generic steppers suitable for sequential or parallel use. */ +trait MakesAnyStepper[A] extends Any { + /** Generates a fresh stepper over `A`s that can be efficiently subdivided */ + def stepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential or parallel use. */ +trait MakesAnyKeyStepper[A] extends Any { + /** Generates a fresh stepper over map keys of type `A` that can be efficiently subdivided */ + def keyStepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential or parallel use. */ +trait MakesAnyValueStepper[A] extends Any { + /** Generates a fresh stepper over map values of type `A` that can be efficiently subdivided */ + def valueStepper: AnyStepper[A] with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers suitable for sequential or parallel use. */ +trait MakesDoubleStepper extends Any { + /** Generates a fresh stepper over `Double`s that can be efficiently subdivided */ + def stepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential or parallel use. */ +trait MakesDoubleKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Double` that can be efficiently subdivided */ + def keyStepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential or parallel use. */ +trait MakesDoubleValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Double` that can be efficiently subdivided */ + def valueStepper: DoubleStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers suitable for sequential or parallel use. */ +trait MakesIntStepper extends Any { + /** Generates a fresh stepper over `Int`s that can be efficiently subdivided */ + def stepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential or parallel use. */ +trait MakesIntKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Int` that can be efficiently subdivided */ + def keyStepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential or parallel use. */ +trait MakesIntValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Int` that can be efficiently subdivided */ + def valueStepper: IntStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers suitable for sequential or parallel use. */ +trait MakesLongStepper extends Any { + /** Generates a fresh stepper over `Long`s that can be efficiently subdivided */ + def stepper: LongStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential or parallel use. */ +trait MakesLongKeyStepper extends Any { + /** Generates a fresh stepper over map keys of type `Long` that can be efficiently subdivided */ + def keyStepper: LongStepper with EfficientSubstep +} + +/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential or parallel use. */ +trait MakesLongValueStepper extends Any { + /** Generates a fresh stepper over map values of type `Long` that can be efficiently subdivided */ + def valueStepper: LongStepper with EfficientSubstep +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 730fef8..cc5a5bc 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -222,7 +222,7 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def nextStep = next def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely: AnyStepper[A] = this override def spliterator: Spliterator[A] = this def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false) @@ -239,7 +239,7 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely: DoubleStepper = this override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false) @@ -256,7 +256,7 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely = this override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false) @@ -273,7 +273,7 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false - def trySplit() = substep.typedPrecisely + def trySplit() = substep match { case null => null; case x => x.typedPrecisely } final def typedPrecisely = this override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 6a452ec..c7806c7 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -135,7 +135,7 @@ class StreamConvertersTest { val hsO = hsetO(n) // Seems like a lot of boilerplate, but we need it to test implicit resolution assertEq(seqO, seqO.seqStream.toScala[Seq]) - //assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well + assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well assertEq(seqO, arrO.seqStream.toScala[Seq]) assertEq(seqO, arrO.parStream.toScala[Seq]) assertEq(seqO, abO.seqStream.toScala[Seq]) @@ -154,7 +154,7 @@ class StreamConvertersTest { val vecD = vectD(n) val hsD = hsetD(n) assertEq(seqD, seqD.seqStream.toScala[Seq]) - //assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) + assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) assertEq(seqD, arrD.seqStream.toScala[Seq]) assertEq(seqD, arrD.parStream.toScala[Seq]) assert(arrD.seqStream.isInstanceOf[DoubleStream]) @@ -183,7 +183,7 @@ class StreamConvertersTest { val vecI = vectI(n) val hsI = hsetI(n) assertEq(seqI, seqI.seqStream.toScala[Seq]) - //assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) + assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) assertEq(seqI, arrI.seqStream.toScala[Seq]) assertEq(seqI, arrI.parStream.toScala[Seq]) assert(arrI.seqStream.isInstanceOf[IntStream]) From 66756d1c4af351a8591c1889ed47afe6da0aee40 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:40:34 -0800 Subject: [PATCH 066/340] Split out steppers for Array, IndexedSeq, LinearSeq, Range, Vector --- .../scala/compat/java8/StepConverters.scala | 265 ------------------ .../java8/collectionImpl/StepsArray.scala | 74 +++++ .../collectionImpl/StepsIndexedSeq.scala | 32 +++ .../java8/collectionImpl/StepsLinearSeq.scala | 41 +++ .../java8/collectionImpl/StepsRange.scala | 32 +++ .../java8/collectionImpl/StepsVector.scala | 129 +++++++++ 6 files changed, 308 insertions(+), 265 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index d88e34c..0669aeb 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,120 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) - } - - private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) - } - - private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE - def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) - } - - private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) - } - - private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) - } - - private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) - } - - private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) - } - - private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) - extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) - } - - private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) - } - - private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) - } - - private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) - } - - private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) - } - - private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { - def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) - } - - private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) - extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) - } - - private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) - extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) - } - - private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) - extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) - } - private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { def semiclone() = new StepsAnyIterator(null) @@ -146,157 +32,6 @@ package converterImpls { def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } - private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) - extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail - def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) - } - - private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) - } - - private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) - extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) - } - - private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { - def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) - } - - private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { - def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) - } - - private[java8] trait StepsVectorLike[A] { - protected def myVector: Vector[A] - protected var index: Int = 32 - protected var data: Array[AnyRef] = null - protected var index1: Int = 32 - protected var data1: Array[AnyRef] = null - protected final def advanceData(iX: Int) { - index1 += 1 - if (index >= 32) initTo(iX) - else { - data = data1(index1).asInstanceOf[Array[AnyRef]] - index = 0 - } - } - protected final def initTo(iX: Int) { - myVector.length match { - case x if x <= 0x20 => - index = iX - data = CollectionInternals.getDisplay0(myVector) - case x if x <= 0x400 => - index1 = iX >>> 5 - data1 = CollectionInternals.getDisplay1(myVector) - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - case x => - var N = 0 - var dataN: Array[AnyRef] = - if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } - else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } - else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } - else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } - while (N > 2) { - dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] - N -= 1 - } - index1 = (iX >>> 5) & 0x1F - data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] - index = iX & 0x1F - data = data1(index1).asInstanceOf[Array[AnyRef]] - } - } - } - - private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) - extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) - with StepsVectorLike[A] { - protected def myVector = underlying - def next() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[A] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsAnyVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) - with StepsVectorLike[Double] { - protected def myVector = underlying - def nextDouble() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Double] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsDoubleVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) - extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) - with StepsVectorLike[Int] { - protected def myVector = underlying - def nextInt() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Int] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsIntVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - - private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) - extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) - with StepsVectorLike[Long] { - protected def myVector = underlying - def nextLong() = if (hasNext()) { - index += 1 - if (index >= 32) advanceData(i0) - i0 += 1 - data(index).asInstanceOf[Long] - } else throwNSEE - def semiclone(half: Int) = { - val ans = new StepsLongVector(underlying, i0, half) - index = 32 - index1 = 32 - i0 = half - ans - } - } - private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala new file mode 100644 index 0000000..13c39ff --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala @@ -0,0 +1,74 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) +} + +private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) +} + +private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE + def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) +} + +private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) +} + +private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) +} + +private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) +} + +private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) +} + +private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) +extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) +} + +private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleArray](_i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleArray(underlying, i0, half) +} + +private[java8] class StepsIntArray(underlying: Array[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntArray](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntArray(underlying, i0, half) +} + +private[java8] class StepsLongArray(underlying: Array[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala new file mode 100644 index 0000000..271cfb6 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyIndexedSeq[A](underlying, i0, half) +} + +private[java8] class StepsDoubleIndexedSeq[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleIndexedSeq[CC]](_i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsDoubleIndexedSeq[CC](underlying, i0, half) +} + +private[java8] class StepsIntIndexedSeq[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntIndexedSeq[CC]](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntIndexedSeq[CC](underlying, i0, half) +} + +private[java8] class StepsLongIndexedSeq[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC, _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala new file mode 100644 index 0000000..947e490 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) +extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) +} + +private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) +extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) +} + +private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) +extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) +} + +private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) +extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { + protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty + protected def myTailOf(cc: CC): CC = cc.tail + def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE + def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala new file mode 100644 index 0000000..8272997 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntRange(underlying, i0, half) +} + +private[java8] class StepsAnyNumericRange[T](underlying: collection.immutable.NumericRange[T], _i0: Int, _iN: Int) +extends StepsLikeIndexed[T, StepsAnyNumericRange[T]](_i0, _iN) { + def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsAnyNumericRange[T](underlying, i0, half) +} + +private[java8] class StepsIntNumericRange(underlying: collection.immutable.NumericRange[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntNumericRange](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsIntNumericRange(underlying, i0, half) +} + +private[java8] class StepsLongNumericRange(underlying: collection.immutable.NumericRange[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { + def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala new file mode 100644 index 0000000..9803ab8 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala @@ -0,0 +1,129 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] trait StepsVectorLike[A] { + protected def myVector: Vector[A] + protected var index: Int = 32 + protected var data: Array[AnyRef] = null + protected var index1: Int = 32 + protected var data1: Array[AnyRef] = null + protected final def advanceData(iX: Int) { + index1 += 1 + if (index >= 32) initTo(iX) + else { + data = data1(index1).asInstanceOf[Array[AnyRef]] + index = 0 + } + } + protected final def initTo(iX: Int) { + myVector.length match { + case x if x <= 0x20 => + index = iX + data = CollectionInternals.getDisplay0(myVector) + case x if x <= 0x400 => + index1 = iX >>> 5 + data1 = CollectionInternals.getDisplay1(myVector) + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + case x => + var N = 0 + var dataN: Array[AnyRef] = + if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVector) } + else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVector) } + else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVector) } + else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVector) } + while (N > 2) { + dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] + N -= 1 + } + index1 = (iX >>> 5) & 0x1F + data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + } + } +} + +private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) +extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) +with StepsVectorLike[A] { + protected def myVector = underlying + def next() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[A] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsAnyVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) +with StepsVectorLike[Double] { + protected def myVector = underlying + def nextDouble() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Double] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsDoubleVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) +with StepsVectorLike[Int] { + protected def myVector = underlying + def nextInt() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Int] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsIntVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + +private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) +extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) +with StepsVectorLike[Long] { + protected def myVector = underlying + def nextLong() = if (hasNext()) { + index += 1 + if (index >= 32) advanceData(i0) + i0 += 1 + data(index).asInstanceOf[Long] + } else throwNSEE + def semiclone(half: Int) = { + val ans = new StepsLongVector(underlying, i0, half) + index = 32 + index1 = 32 + i0 = half + ans + } +} + + From 2674205b248f77de0571cafba6f2db7b4e320b46 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Nov 2015 20:56:06 -0800 Subject: [PATCH 067/340] Pulled out more steppers. This time: BitSet, FlatHashTable, HashTable, and immutable sets and maps (trie-based). --- .../scala/compat/java8/StepConverters.scala | 307 ------------------ .../java8/collectionImpl/StepsBitSet.scala | 47 +++ .../collectionImpl/StepsFlatHashTable.scala | 33 ++ .../java8/collectionImpl/StepsHashTable.scala | 137 ++++++++ .../collectionImpl/StepsImmHashMap.scala | 122 +++++++ .../collectionImpl/StepsImmHashSet.scala | 33 ++ 6 files changed, 372 insertions(+), 307 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 0669aeb..f9aadd2 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -32,313 +32,6 @@ package converterImpls { def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } - private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) - } - - private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } - def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) - } - - private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) - extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) - } - - private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) - } - - private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) - } - - private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) - } - - private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) - } - - private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) - } - - private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) - } - - private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) - } - - private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) - } - - private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } - def semiclone(half: Int) = - new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) - } - - private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) - extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) - } - - private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) - extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) - } - - private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) - extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) - } - - private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) - extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = - if (currentEntry eq null) throwNSEE - else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } - def semiclone(half: Int) = - new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) - } - - private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) - def next(): (K, V) = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.iterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) - def next(): K = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) - extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) - def next(): V = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) - extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) - extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) - def nextDouble() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) - extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) - extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) - def nextInt() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) - extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.keysIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) - extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { - protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) - def nextLong() = - if (hasNext) { - if (theIterator eq null) theIterator = underlying.valuesIterator - i += 1 - theIterator.next - } - else throwNSEE - } - - private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) - extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { - protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) - def next(): A = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) - extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) - def nextDouble() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) - extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) - def nextInt() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) - extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { - protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) - def nextLong() = { val ans = underlying.next; i += 1; ans } - } - - private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) - extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { - private var mask: Long = (-1L) << (i & 0x3F) - private var cache: Long = underlying(i >>> 6) - private var found: Boolean = false - def semiclone(half: Int) = { - val ans = new StepsIntBitSet(underlying, i, half) - i = half - mask = (-1L) << (i & 0x3F) - cache = underlying(i >>> 6) - found = false - ans - } - def hasNext(): Boolean = found || ((i < iN) && { - while ((mask & cache) == 0) { - i += java.lang.Long.numberOfLeadingZeros(~mask) - if (i < 0 || i >= iN) { i = iN; return false } - mask = -1L - cache = underlying(i >>> 6) - } - var m = mask << 1 - while ((mask & cache) == (m & cache)) { - mask = m - m = mask << 1 - i += 1 - } - if (i < 0 || i >= iN) { - i = iN - false - } - else { - found = true - true - } - }) - def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE - } final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala new file mode 100644 index 0000000..735dc04 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala @@ -0,0 +1,47 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) +extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { + private var mask: Long = (-1L) << (i & 0x3F) + private var cache: Long = underlying(i >>> 6) + private var found: Boolean = false + def semiclone(half: Int) = { + val ans = new StepsIntBitSet(underlying, i, half) + i = half + mask = (-1L) << (i & 0x3F) + cache = underlying(i >>> 6) + found = false + ans + } + def hasNext(): Boolean = found || ((i < iN) && { + while ((mask & cache) == 0) { + i += java.lang.Long.numberOfLeadingZeros(~mask) + if (i < 0 || i >= iN) { i = iN; return false } + mask = -1L + cache = underlying(i >>> 6) + } + var m = mask << 1 + while ((mask & cache) == (m & cache)) { + mask = m + m = mask << 1 + i += 1 + } + if (i < 0 || i >= iN) { + i = iN + false + } + else { + found = true + true + } + }) + def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala new file mode 100644 index 0000000..c634e37 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsAnyFlatHashTable[A](underlying, i0, half) +} + +private[java8] class StepsDoubleFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleFlatHashTable](_underlying, _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Double]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsDoubleFlatHashTable(underlying, i0, half) +} + +private[java8] class StepsIntFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntFlatHashTable](_underlying, _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Int]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsIntFlatHashTable(underlying, i0, half) +} + +private[java8] class StepsLongFlatHashTable(_underlying: Array[AnyRef], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[Long]; currentEntry = null; ans } + def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala new file mode 100644 index 0000000..d7ede16 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala @@ -0,0 +1,137 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +//////////////////////////// +// Steppers for keys (type of HashEntry doesn't matter) +//////////////////////////// + +private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) +extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) +} + +private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) +} + +private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) +} + +private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } + def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) +} + +//////////////////////////// +// Steppers for entries stored in DefaultEntry HashEntry +// (both for key-value pair and for values alone) +//////////////////////////// + +private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyDefaultHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) +} + +private[java8] class StepsAnyDefaultHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[V, StepsAnyDefaultHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyDefaultHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]]], i0, half) +} + +private[java8] class StepsDoubleDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], i0, half) +} + +private[java8] class StepsIntDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int]]]], i0, half) +} + +private[java8] class StepsLongDefaultHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.DefaultEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) +} + +//////////////////////////// +// Steppers for entries stored in LinkedEntry HashEntry +// (both for key-value pair and for values alone) +//////////////////////////// + +private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; (de.key, de.value) } + def semiclone(half: Int) = + new StepsAnyLinkedHashTable[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) +} + +private[java8] class StepsAnyLinkedHashTableValue[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) +extends StepsLikeGapped[V, StepsAnyLinkedHashTableValue[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, V]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsAnyLinkedHashTableValue[K, V](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]]], i0, half) +} + +private[java8] class StepsDoubleLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Double]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsDoubleLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], i0, half) +} + +private[java8] class StepsIntLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Int]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsIntLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int]]]], i0, half) +} + +private[java8] class StepsLongLinkedHashTableValue[K](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = + if (currentEntry eq null) throwNSEE + else { val de = currentEntry.asInstanceOf[collection.mutable.LinkedEntry[K, Long]]; currentEntry = de.next; de.value } + def semiclone(half: Int) = + new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala new file mode 100644 index 0000000..6f28563 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala @@ -0,0 +1,122 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +////////////////////// +// Note that there are separate implementations for keys, values, and key-value pairs +///////////////////// + +private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMap[K, V](u, j0, jN) + def next(): (K, V) = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.iterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsAnyImmHashMapKey[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, K, StepsAnyImmHashMapKey[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapKey[K, V](u, j0, jN) + def next(): K = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsAnyImmHashMapValue[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +extends StepsLikeImmHashMap[K, V, V, StepsAnyImmHashMapValue[K, V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int) = new StepsAnyImmHashMapValue[K, V](u, j0, jN) + def next(): V = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsDoubleImmHashMapKey[V](_underlying: collection.immutable.HashMap[Double, V], _i0: Int, _iN: Int) +extends StepsDoubleLikeImmHashMap[Double, V, StepsDoubleImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Double,V], j0: Int, jN: Int) = new StepsDoubleImmHashMapKey[V](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsDoubleImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Double], _i0: Int, _iN: Int) +extends StepsDoubleLikeImmHashMap[K, Double, StepsDoubleImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Double], j0: Int, jN: Int) = new StepsDoubleImmHashMapValue[K](u, j0, jN) + def nextDouble() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsIntImmHashMapKey[V](_underlying: collection.immutable.HashMap[Int, V], _i0: Int, _iN: Int) +extends StepsIntLikeImmHashMap[Int, V, StepsIntImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Int,V], j0: Int, jN: Int) = new StepsIntImmHashMapKey[V](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsIntImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Int], _i0: Int, _iN: Int) +extends StepsIntLikeImmHashMap[K, Int, StepsIntImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Int], j0: Int, jN: Int) = new StepsIntImmHashMapValue[K](u, j0, jN) + def nextInt() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsLongImmHashMapKey[V](_underlying: collection.immutable.HashMap[Long, V], _i0: Int, _iN: Int) +extends StepsLongLikeImmHashMap[Long, V, StepsLongImmHashMapKey[V]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[Long,V], j0: Int, jN: Int) = new StepsLongImmHashMapKey[V](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.keysIterator + i += 1 + theIterator.next + } + else throwNSEE +} + +private[java8] class StepsLongImmHashMapValue[K](_underlying: collection.immutable.HashMap[K, Long], _i0: Int, _iN: Int) +extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlying, _i0, _iN) { + protected def demiclone(u: collection.immutable.HashMap[K,Long], j0: Int, jN: Int) = new StepsLongImmHashMapValue[K](u, j0, jN) + def nextLong() = + if (hasNext) { + if (theIterator eq null) theIterator = underlying.valuesIterator + i += 1 + theIterator.next + } + else throwNSEE +} + + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala new file mode 100644 index 0000000..a6edb7b --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) +extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { + protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) + def next(): A = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsDoubleImmHashSet(_underlying: Iterator[Double], _N: Int) +extends StepsDoubleLikeTrieIterator[StepsDoubleImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Double], N: Int) = new StepsDoubleImmHashSet(it, N) + def nextDouble() = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsIntImmHashSet(_underlying: Iterator[Int], _N: Int) +extends StepsIntLikeTrieIterator[StepsIntImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Int], N: Int) = new StepsIntImmHashSet(it, N) + def nextInt() = { val ans = underlying.next; i += 1; ans } +} + +private[java8] class StepsLongImmHashSet(_underlying: Iterator[Long], _N: Int) +extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { + protected def demiclone(it: Iterator[Long], N: Int) = new StepsLongImmHashSet(it, N) + def nextLong() = { val ans = underlying.next; i += 1; ans } +} + From 4c5f0a1653d5e3193ff59db1819fd498420bcf8d Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 13:41:07 -0800 Subject: [PATCH 068/340] Moved Iterator and String steppers to their own files. --- .../scala/compat/java8/StepConverters.scala | 49 ------------------- .../java8/collectionImpl/StepsIterator.scala | 32 ++++++++++++ .../java8/collectionImpl/StepsString.scala | 33 +++++++++++++ 3 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index f9aadd2..b6d1b8f 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,31 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) - extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { - def semiclone() = new StepsAnyIterator(null) - def next() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) - extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { - def semiclone() = new StepsDoubleIterator(null) - def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsIntIterator(_underlying: Iterator[Int]) - extends StepsIntLikeIterator[StepsIntIterator](_underlying) { - def semiclone() = new StepsIntIterator(null) - def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next - } - - private[java8] class StepsLongIterator(_underlying: Iterator[Long]) - extends StepsLongLikeIterator[StepsLongIterator](_underlying) { - def semiclone() = new StepsLongIterator(null) - def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next - } - - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) } @@ -311,30 +286,6 @@ package converterImpls { def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] } - private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { - def characteristics() = NonNull - def estimateSize = iN - i0 - def hasNext = i0 < iN - def nextInt() = { - if (hasNext()) { - val cp = underlying.codePointAt(i0) - i0 += java.lang.Character.charCount(cp) - cp - } - else throwNSEE - } - def substep() = { - if (iN-3 > i0) { - var half = (i0+iN) >>> 1 - if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 - val ans = new StepperStringCodePoint(underlying, i0, half) - i0 = half - ans - } - else null - } - } - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala new file mode 100644 index 0000000..ade3055 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala @@ -0,0 +1,32 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) +extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { + def semiclone() = new StepsAnyIterator(null) + def next() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsDoubleIterator(_underlying: Iterator[Double]) +extends StepsDoubleLikeIterator[StepsDoubleIterator](_underlying) { + def semiclone() = new StepsDoubleIterator(null) + def nextDouble() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsIntIterator(_underlying: Iterator[Int]) +extends StepsIntLikeIterator[StepsIntIterator](_underlying) { + def semiclone() = new StepsIntIterator(null) + def nextInt() = if (proxied ne null) proxied.nextStep else underlying.next +} + +private[java8] class StepsLongIterator(_underlying: Iterator[Long]) +extends StepsLongLikeIterator[StepsLongIterator](_underlying) { + def semiclone() = new StepsLongIterator(null) + def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala new file mode 100644 index 0000000..b8b37d2 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala @@ -0,0 +1,33 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { + def characteristics() = NonNull + def estimateSize = iN - i0 + def hasNext = i0 < iN + def nextInt() = { + if (hasNext()) { + val cp = underlying.codePointAt(i0) + i0 += java.lang.Character.charCount(cp) + cp + } + else throwNSEE + } + def substep() = { + if (iN-3 > i0) { + var half = (i0+iN) >>> 1 + if (java.lang.Character.isLowSurrogate(underlying.charAt(half))) half -= 1 + val ans = new StepperStringCodePoint(underlying, i0, half) + i0 = half + ans + } + else null + } +} + From 02d56d568725183f51770c14c264cadb8d51d709 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 14:26:56 -0800 Subject: [PATCH 069/340] Moved all value classes out of StepConverters. --- .../scala/compat/java8/StepConverters.scala | 437 ------------------ .../java8/collectionImpl/Accumulates.scala | 74 +++ .../java8/collectionImpl/StepsArray.scala | 52 +++ .../java8/collectionImpl/StepsBitSet.scala | 23 + .../collectionImpl/StepsFlatHashTable.scala | 35 ++ .../java8/collectionImpl/StepsHashTable.scala | 134 +++++- .../collectionImpl/StepsImmHashMap.scala | 40 +- .../collectionImpl/StepsImmHashSet.scala | 23 + .../collectionImpl/StepsIndexedSeq.scala | 24 + .../java8/collectionImpl/StepsIterable.scala | 27 ++ .../java8/collectionImpl/StepsIterator.scala | 25 + .../java8/collectionImpl/StepsLinearSeq.scala | 23 + .../java8/collectionImpl/StepsMap.scala | 41 ++ .../java8/collectionImpl/StepsRange.scala | 24 + .../java8/collectionImpl/StepsString.scala | 11 + .../java8/collectionImpl/StepsVector.scala | 22 + 16 files changed, 570 insertions(+), 445 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index b6d1b8f..13ba8d0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -8,381 +8,6 @@ import scala.compat.java8.runtime._ package converterImpls { import Stepper._ - final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) - } - - final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) - } - - final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { - @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) - } - - final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { - @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) - } - - final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { - @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) - } - - final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { - @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) - } - - final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { - @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) - } - - final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { - @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) - } - - final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) - } - - final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) - } - - final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) - } - - final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) - } - - final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) - } - - final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) - } - - final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntIterator(underlying) - } - - final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongIterator(underlying) - } - - final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { - @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) - } - - final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) - } - - final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsAnyFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsDoubleFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsIntFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable(underlying) - new StepsLongFlatHashTable(tbl, 0, tbl.length) - } - } - - final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) - extends AnyVal with MakesAnyKeyStepper[K] { - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, HE](underlying) - new StepsAnyHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) - extends AnyVal with MakesDoubleKeyStepper { - @inline def keyStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Double, HE](underlying) - new StepsDoubleHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) - extends AnyVal with MakesIntKeyStepper { - @inline def keyStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Int, HE](underlying) - new StepsIntHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) - extends AnyVal with MakesLongKeyStepper { - @inline def keyStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[Long, HE](underlying) - new StepsLongHashTableKey(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) - extends AnyVal with MakesAnyStepper[(K, V)] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTable(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) - extends AnyVal with MakesAnyValueStepper[V] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) - extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) - new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) - extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) - new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) - extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) - new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) - extends AnyVal with MakesAnyStepper[(K,V)] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTable(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) - extends AnyVal with MakesAnyValueStepper[V] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) - extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) - new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) - extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) - new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) - extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = runtime.CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) - new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) - } - } - - final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) - extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { - @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) - } - - final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { - @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { - @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { - @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { - @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { - @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) - } - - final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { - @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) - } - - final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) - } - - final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { - def stepper: IntStepper with EfficientSubstep = { - val bits: Array[Long] = underlying match { - case m: collection.mutable.BitSet => runtime.CollectionInternals.getBitSetInternals(m) - case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) - case x => x.toBitMask - } - new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) - } - } - private[java8] object RichBitSetCanStep { - private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") - def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] - } - - final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { - def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) - def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) - } - - final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { - def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) - } - - final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { - def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) - } - - final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { - def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) - } - - final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { - def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) - } - - final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { - def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) - } - - final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { - def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) - } - - final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) - } - - final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) - } - - final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { - @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) - } - - final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { - @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) - } - - final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) - } - - final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) - } - - final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) - } - - final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) - } - - final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) - } - - final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) - } - - final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) - } - - final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) - } - - final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) - } - - final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) - } - - final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) - } - - final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) - } - - final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) - } - trait Priority7StepConverters { implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) } @@ -505,68 +130,6 @@ package converterImpls { implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } - final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - underlying.foreach(a += _) - a - } - } - - final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - underlying.foreach(da += _) - da - } - } - final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { - def accumulate: Accumulator[A] = { - val a = new Accumulator[A] - var i = 0 - while (i < underlying.length) { a += underlying(i); i += 1 } - a - } - } - - final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { - def accumulate: DoubleAccumulator = { - val da = new DoubleAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } - final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { - def accumulate: IntAccumulator = { - val da = new IntAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } - final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { - def accumulate: LongAccumulator = { - val da = new LongAccumulator - var i = 0 - while (i < underlying.length) { da += underlying(i); i += 1 } - da - } - } trait Priority3AccumulatorConverters { implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala new file mode 100644 index 0000000..ae4e6fe --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala @@ -0,0 +1,74 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + underlying.foreach(a += _) + a + } +} + +final class AccumulateDoubleCollection(private val underlying: TraversableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateIntCollection(private val underlying: TraversableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateLongCollection(private val underlying: TraversableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + underlying.foreach(da += _) + da + } +} + +final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { + def accumulate: Accumulator[A] = { + val a = new Accumulator[A] + var i = 0 + while (i < underlying.length) { a += underlying(i); i += 1 } + a + } +} + +final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = { + val da = new DoubleAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} + +final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { + def accumulate: IntAccumulator = { + val da = new IntAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} + +final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { + def accumulate: LongAccumulator = { + val da = new LongAccumulator + var i = 0 + while (i < underlying.length) { da += underlying(i); i += 1 } + da + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala index 13c39ff..b9177d0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsArray.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsObjectArray[A <: Object](underlying: Array[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -72,3 +76,51 @@ extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongArray(underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) +} + +final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) +} + +final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { + @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) +} + +final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { + @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) +} + +final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { + @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) +} + +final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { + @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) +} + +final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { + @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) +} + +final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { + @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) +} + +final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) +} + +final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) +} + +final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala index 735dc04..c3fac1c 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsBitSet.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +//////////////////////////// +// Stepper implementation // +//////////////////////////// + private[java8] class StepsIntBitSet(_underlying: Array[Long], _i0: Int, _iN: Int) extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { private var mask: Long = (-1L) << (i & 0x3F) @@ -45,3 +49,22 @@ extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { def nextInt() = if (hasNext) { val j = i; found = false; mask = mask << 1; i += 1; j } else throwNSEE } +///////////////////////// +// Value class adapter // +///////////////////////// + +final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { + def stepper: IntStepper with EfficientSubstep = { + val bits: Array[Long] = underlying match { + case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) + case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) + case x => x.toBitMask + } + new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) + } +} +private[java8] object RichBitSetCanStep { + private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") + def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala index c634e37..144a4df 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsFlatHashTable.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyFlatHashTable[A](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends StepsLikeGapped[A, StepsAnyFlatHashTable[A]](_underlying, _i0, _iN) { def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[A]; currentEntry = null; ans } @@ -31,3 +35,34 @@ extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { def semiclone(half: Int) = new StepsLongFlatHashTable(underlying, i0, half) } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsAnyFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsDoubleFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsIntFlatHashTable(tbl, 0, tbl.length) + } +} + +final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable(underlying) + new StepsLongFlatHashTable(tbl, 0, tbl.length) + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala index d7ede16..def363e 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsHashTable.scala @@ -7,9 +7,11 @@ import scala.compat.java8.runtime._ import Stepper._ -//////////////////////////// +///////////////////////////// +// Stepper implementations // +///////////////////////////// + // Steppers for keys (type of HashEntry doesn't matter) -//////////////////////////// private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -35,10 +37,8 @@ extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[ def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) } -//////////////////////////// // Steppers for entries stored in DefaultEntry HashEntry // (both for key-value pair and for values alone) -//////////////////////////// private[java8] class StepsAnyDefaultHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, V]]], _i0: Int, _iN: Int) extends StepsLikeGapped[(K, V), StepsAnyDefaultHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -85,10 +85,8 @@ extends StepsLongLikeGapped[StepsLongDefaultHashTableValue[K]](_underlying.asIns new StepsLongDefaultHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long]]]], i0, half) } -//////////////////////////// // Steppers for entries stored in LinkedEntry HashEntry // (both for key-value pair and for values alone) -//////////////////////////// private[java8] class StepsAnyLinkedHashTable[K, V](_underlying: Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, V]]], _i0: Int, _iN: Int) extends StepsLikeGapped[(K, V), StepsAnyLinkedHashTable[K, V]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { @@ -135,3 +133,127 @@ extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInst new StepsLongLinkedHashTableValue[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long]]]], i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +// Steppers for keys (type of HashEntry doesn't matter) + +final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) +extends AnyVal with MakesAnyKeyStepper[K] { + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, HE](underlying) + new StepsAnyHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) +extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Double, HE](underlying) + new StepsDoubleHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) +extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Int, HE](underlying) + new StepsIntHashTableKey(tbl, 0, tbl.length) + } +} + +final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) +extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[Long, HE](underlying) + new StepsLongHashTableKey(tbl, 0, tbl.length) + } +} + +// Steppers for entries stored in DefaultEntry HashEntry +// (both for key-value pair and for values alone) + +final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) +extends AnyVal with MakesAnyStepper[(K, V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTable(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) +extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) +extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) + new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) +extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) + new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) +extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) + new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) + } +} + +// Steppers for entries stored in LinkedEntry HashEntry +// (both for key-value pair and for values alone) + +final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) +extends AnyVal with MakesAnyStepper[(K,V)] { + @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTable(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) +extends AnyVal with MakesAnyValueStepper[V] { + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) +extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) + new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) +extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) + new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) + } +} + +final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) +extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) + new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) + } +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala index 6f28563..65b69dd 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashMap.scala @@ -7,9 +7,11 @@ import scala.compat.java8.runtime._ import Stepper._ -////////////////////// // Note that there are separate implementations for keys, values, and key-value pairs -///////////////////// + +///////////////////////////// +// Stepper implementations // +///////////////////////////// private[java8] class StepsAnyImmHashMap[K, V](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLikeImmHashMap[K, V, (K, V), StepsAnyImmHashMap[K, V]](_underlying, _i0, _iN) { @@ -119,4 +121,38 @@ extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlyin else throwNSEE } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) +extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { + @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) + @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) +} + +final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { + @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) +} + +final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { + @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) +} + +final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { + @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) +} + +final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { + @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) +} + +final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { + @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) +} +final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { + @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala index a6edb7b..0f9c2e0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsImmHashSet.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyImmHashSet[A](_underlying: Iterator[A], _N: Int) extends StepsLikeTrieIterator[A, StepsAnyImmHashSet[A]](_underlying, _N) { protected def demiclone(it: Iterator[A], N: Int) = new StepsAnyImmHashSet(it, N) @@ -31,3 +35,22 @@ extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { def nextLong() = { val ans = underlying.next; i += 1; ans } } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) +} + +final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) +} + +final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) +} + +final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala index 271cfb6..65c2232 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIndexedSeq.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyIndexedSeq[A](underlying: collection.IndexedSeqLike[A, _], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsAnyIndexedSeq[A]](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -30,3 +34,23 @@ extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongIndexedSeq[CC](underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) +} + +final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) +} + +final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) +} + +final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala new file mode 100644 index 0000000..70a6bca --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterable.scala @@ -0,0 +1,27 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +// Iterables just defer to iterator unless they can pattern match something better. +// TODO: implement pattern matching! + +final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) +} + +final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) +} + +final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) +} + +final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala index ade3055..eb951d6 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsIterator.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyIterator[A](_underlying: Iterator[A]) extends StepsLikeIterator[A, StepsAnyIterator[A]](_underlying) { def semiclone() = new StepsAnyIterator(null) @@ -30,3 +34,24 @@ extends StepsLongLikeIterator[StepsLongIterator](_underlying) { def semiclone() = new StepsLongIterator(null) def nextLong() = if (proxied ne null) proxied.nextStep else underlying.next } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) +} + +final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) +} + +final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntIterator(underlying) +} + +final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongIterator(underlying) +} + diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala index 947e490..e809424 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty @@ -39,3 +43,22 @@ extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { + @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) +} + +final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { + @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) +} + +final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { + @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) +} + +final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { + @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala new file mode 100644 index 0000000..fcaaa67 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala @@ -0,0 +1,41 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.runtime._ + +import Stepper._ + +// Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching +// TODO: implement pattern matching + +final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { + // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here + def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) + def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) +} + +final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { + def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) +} + +final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { + def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) +} + +final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { + def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) +} + +final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { + def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) +} + +final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { + def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) +} + +final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { + def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala index 8272997..1eb1282 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] class StepsIntRange(underlying: Range, _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepsIntRange](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -30,3 +34,23 @@ extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { def nextLong() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE def semiclone(half: Int) = new StepsLongNumericRange(underlying, i0, half) } + +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) +} + +final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { + @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) +} + +final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) +} + +final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala index b8b37d2..d3bccc0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +//////////////////////////// +// Stepper implementation // +//////////////////////////// + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { def characteristics() = NonNull def estimateSize = iN - i0 @@ -31,3 +35,10 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var } } +///////////////////////// +// Value class adapter // +///////////////////////// + +final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) +} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala index 9803ab8..12923c9 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala @@ -7,6 +7,10 @@ import scala.compat.java8.runtime._ import Stepper._ +///////////////////////////// +// Stepper implementations // +///////////////////////////// + private[java8] trait StepsVectorLike[A] { protected def myVector: Vector[A] protected var index: Int = 32 @@ -126,4 +130,22 @@ with StepsVectorLike[Long] { } } +////////////////////////// +// Value class adapters // +////////////////////////// + +final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { + @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) +} + +final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) +} + +final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { + @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) +} +final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { + @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) +} From c96039d32820cd5bbed68a4e98800dbbabbd3d63 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sun, 29 Nov 2015 14:37:11 -0800 Subject: [PATCH 070/340] Made StreamConverters responsible for Steps and Accumulators also. Split out Accumulators from StepConverters so StepConverters could just be hierarchy of traits for implicit conversion. --- .../scala/compat/java8/StepConverters.scala | 268 ++++++++---------- .../scala/compat/java8/StreamConverters.scala | 6 +- .../AccumulatorConverters.scala | 20 ++ .../compat/java8/StepConvertersTest.scala | 2 +- .../compat/java8/StreamConvertersTest.scala | 1 - 5 files changed, 148 insertions(+), 149 deletions(-) create mode 100644 src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala diff --git a/src/main/scala/scala/compat/java8/StepConverters.scala b/src/main/scala/scala/compat/java8/StepConverters.scala index 13ba8d0..85b42f0 100644 --- a/src/main/scala/scala/compat/java8/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/StepConverters.scala @@ -1,155 +1,131 @@ -package scala.compat.java8 +package scala.compat.java8.converterImpls import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ -package converterImpls { - import Stepper._ - - trait Priority7StepConverters { - implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) - } - - trait Priority6StepConverters extends Priority7StepConverters { - implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) - implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) - implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) - implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) - } - - trait Priority5StepConverters extends Priority6StepConverters { - implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) - implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) - implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) - implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) - implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) - implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) - } - - trait Priority4StepConverters extends Priority5StepConverters { - implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) - implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = - new RichHashTableKeyCanStep[K, HE](underlying) - implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableCanStep[K, V](underlying) - implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableValueCanStep[K, V](underlying) - implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableCanStep[K, V](underlying) - implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableValueCanStep[K, V](underlying) - } - - trait Priority3StepConverters extends Priority4StepConverters { - implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = - new RichIndexedSeqCanStep[A](underlying) - implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) - implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = - new RichDoubleLinearSeqCanStep[CC](underlying) - implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = - new RichIntLinearSeqCanStep[CC](underlying) - implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = - new RichLongLinearSeqCanStep[CC](underlying) - implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = - new RichHashTableDoubleKeyCanStep[HE](underlying) - implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = - new RichHashTableIntKeyCanStep[HE](underlying) - implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = - new RichHashTableLongKeyCanStep[HE](underlying) - implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = - new RichDefaultHashTableDoubleValueCanStep[K](underlying) - implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = - new RichDefaultHashTableIntValueCanStep[K](underlying) - implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = - new RichDefaultHashTableLongValueCanStep[K](underlying) - implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = - new RichLinkedHashTableDoubleValueCanStep[K](underlying) - implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = - new RichLinkedHashTableIntValueCanStep[K](underlying) - implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = - new RichLinkedHashTableLongValueCanStep[K](underlying) - - implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) - implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) - } +import Stepper._ + +trait Priority7StepConverters { + implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) +} + +trait Priority6StepConverters extends Priority7StepConverters { + implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) + implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) + implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) + implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) +} + +trait Priority5StepConverters extends Priority6StepConverters { + implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) + implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) + implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) + implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) + implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) + implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) +} + +trait Priority4StepConverters extends Priority5StepConverters { + implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) + implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = + new RichHashTableKeyCanStep[K, HE](underlying) + implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableCanStep[K, V](underlying) + implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = + new RichDefaultHashTableValueCanStep[K, V](underlying) + implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableCanStep[K, V](underlying) + implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = + new RichLinkedHashTableValueCanStep[K, V](underlying) +} + +trait Priority3StepConverters extends Priority4StepConverters { + implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) + implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = + new RichIndexedSeqCanStep[A](underlying) + implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) + implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = + new RichDoubleLinearSeqCanStep[CC](underlying) + implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = + new RichIntLinearSeqCanStep[CC](underlying) + implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = + new RichLongLinearSeqCanStep[CC](underlying) + implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) + implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = + new RichHashTableDoubleKeyCanStep[HE](underlying) + implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = + new RichHashTableIntKeyCanStep[HE](underlying) + implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = + new RichHashTableLongKeyCanStep[HE](underlying) + implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = + new RichDefaultHashTableDoubleValueCanStep[K](underlying) + implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = + new RichDefaultHashTableIntValueCanStep[K](underlying) + implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = + new RichDefaultHashTableLongValueCanStep[K](underlying) + implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = + new RichLinkedHashTableDoubleValueCanStep[K](underlying) + implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = + new RichLinkedHashTableIntValueCanStep[K](underlying) + implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = + new RichLinkedHashTableLongValueCanStep[K](underlying) + + implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) + implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) +} + +trait Priority2StepConverters extends Priority3StepConverters { + implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) + implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) + implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) + implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) + implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) + implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) + implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = + new RichDoubleIndexedSeqCanStep[CC](underlying) + implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = + new RichIntIndexedSeqCanStep[CC](underlying) + implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = + new RichLongIndexedSeqCanStep[CC](underlying) + implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) + implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) + implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) + implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) + implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) + implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) + implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) + implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) + + implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) + implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) + implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) + implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) + implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) + implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) + + implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) +} + +trait Priority1StepConverters extends Priority2StepConverters { + implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) + implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) + implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - trait Priority2StepConverters extends Priority3StepConverters { - implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) - implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) - implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) - implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) - implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) - implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) - implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) - implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = - new RichDoubleIndexedSeqCanStep[CC](underlying) - implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = - new RichIntIndexedSeqCanStep[CC](underlying) - implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = - new RichLongIndexedSeqCanStep[CC](underlying) - implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) - implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) - implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) - implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) - implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) - implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) - implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) - implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) - - implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) - implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) - implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) - implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) - implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) - implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) - - implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) - } - - trait Priority1StepConverters extends Priority2StepConverters { - implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) - implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) - implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - - implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) - implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) - implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - - implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) - implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) - implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) - - implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) - implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) - implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) - - implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) - } - - - trait Priority3AccumulatorConverters { - implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) - } - - trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { - implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) - implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) - implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) - implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) - } - - trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { - implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) - implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) - implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) - } + implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) + implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) + implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) + + implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) + implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) + implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) + + implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) + implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) + implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) + + implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } -object StepConverters -extends converterImpls.Priority1StepConverters -with converterImpls.Priority1AccumulatorConverters -{} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 60d7114..a6ae6d1 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -167,7 +167,11 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] * ``` */ -object StreamConverters extends Priority1StreamConverters { +object StreamConverters +extends Priority1StreamConverters +with converterImpls.Priority1StepConverters +with converterImpls.Priority1AccumulatorConverters +{ implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala new file mode 100644 index 0000000..1f44f97 --- /dev/null +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala @@ -0,0 +1,20 @@ +package scala.compat.java8.converterImpls + +import language.implicitConversions + +trait Priority3AccumulatorConverters { + implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) +} + +trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { + implicit def accumulateDoubleCollection(underlying: TraversableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: TraversableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: TraversableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) +} + +trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { + implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) +} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index c3f1663..ac18a7c 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -6,7 +6,7 @@ import org.junit.Assert._ class StepConvertersTest { import java.util._ import collectionImpl._ - import StepConverters._ + import StreamConverters._ // Includes StepConverters! import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index c7806c7..b1ad2f5 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -6,7 +6,6 @@ import org.junit.Assert._ class StreamConvertersTest { import java.util.stream._ import StreamConverters._ - import StepConverters._ def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } From 043672b032911f959ab8f80306f37a18c9c12c2a Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 30 Nov 2015 19:41:22 -0800 Subject: [PATCH 071/340] Java class full of static methods that give streams from collections. --- README.md | 49 +- .../scala/compat/java8/ScalaStreaming.java | 904 ++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 60 +- .../java8/collectionImpl/Accumulates.scala | 4 + .../java8/collectionImpl/Accumulator.scala | 7 + .../AccumulatorConverters.scala | 15 + .../collectionImpl/DoubleAccumulator.scala | 7 + .../java8/collectionImpl/IntAccumulator.scala | 7 + .../collectionImpl/LongAccumulator.scala | 7 + .../compat/java8/collectionImpl/Stepper.scala | 16 +- 10 files changed, 1068 insertions(+), 8 deletions(-) create mode 100644 src/main/java/scala/compat/java8/ScalaStreaming.java diff --git a/README.md b/README.md index b3f11ba..b757697 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,49 @@ class Test { ``` -## Future work - - Converters for `java.util.stream` - - [`Spliterator`](https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html)s for Scala collections +## Converters from Scala collections to Java 8 Streams + +Scala collections gain `seqStream` and `parStream` as extension methods that produce a Java 8 Stream +running sequentially or in parallel, respectively. These are automatically specialized to a primitive +type if possible. For instance, `List(1,2).seqStream` produces an `IntStream`. Maps additionally have +`seqKeyStream`, `seqValueStream`, `parKeyStream`, and `parValueStream` methods. + +Scala collections also gain `accumulate` and `stepper` methods that produce utility collections that +can be useful when working with Java 8 Streams. `accumulate` produces an `Accumulator` or its primitive +counterpart (`DoubleAccumulator`, etc.), which is a low-level collection designed for efficient collection +and dispatching of results to and from Streams. Unlike most collections, it can contain more than +`Int.MaxValue` elements. `stepper` produces a `Stepper` which is a fusion of `Spliterator` and `Iterator`. +`Stepper`s underlie the Scala collections' instances of Java 8 Streams. + +Java 8 Streams gain `toScala[Coll]` and `accumulate` methods, to make it easy to produce Scala collections +or Accumulators, respectively, from Java 8 Streams. For instance, `myStream.to[Vector]` will collect the +contents of a Stream into a `scala.collection.immutable.Vector`. Note that standard sequential builders +are used for collections, so this is best done to gather the results of an expensive computation. + +Finally, there is a Java class, `ScalaStreamer`, that has a series of `from` methods that can be used to +obtain Java 8 Streams from Scala collections from within Java. + +#### Scala Usage Example + +```scala +import scala.compat.java8.StreamConverters._ + +object Test { + val m = collection.immutable.HashMap("fish" -> 2, "bird" -> 4) + val s = m.parValueStream.sum // 6, potientially computed in parallel + val t = m.seqKeyStream.toScala[List] // List("fish", "bird") + val a = t.accumulate // Accumulator[(String, Int)] + + val n = a.splitter.fold(0)(_ + _._1.length) + + a.parStream.count // 8 + 2 = 10 + + val b = java.util.Arrays.stream(Array(2L, 3L, 4L)). + accumulate // LongAccumulator +} +``` + +#### Java Usage Example + +```java +// TODO -- write converter and create example +``` diff --git a/src/main/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreaming.java new file mode 100644 index 0000000..b32ae32 --- /dev/null +++ b/src/main/java/scala/compat/java8/ScalaStreaming.java @@ -0,0 +1,904 @@ +package scala.compat.java8; + +import scala.compat.java8.converterImpls.*; +import java.util.stream.*; +import scala.compat.java8.runtime.CollectionInternals; + +public class ScalaStreaming { + ///////////////////// + // Generic Streams // + ///////////////////// + + /** + * Generates a Stream that traverses an IndexedSeq. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.IndexedSeq coll) { + return StreamSupport.stream(new StepsAnyIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.immutable.HashMap. + * The key-value pairs are presented as instances of scala.Tuple2. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.immutable.HashMap coll) { + return StreamSupport.stream(new StepsAnyImmHashMap(coll, 0, coll.size()), false); + } + + /** + * Generates a Stream that traverses a scala.collection.immutable.HashSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.immutable.HashSet coll) { + return StreamSupport.stream(new StepsAnyImmHashSet(coll.iterator(), coll.size()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.mutable.HashMap. + * The key-value pairs are presented as instances of scala.Tuple2. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry< K, scala.collection.mutable.DefaultEntry >[] tbl = + CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyDefaultHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses a scala.collection.mutable.HashSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.stream(new StepsAnyFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a Stream that traverses a scala.collection.immutable.Vector. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.immutable.Vector coll) { + return StreamSupport.stream(new StepsAnyVector(coll, 0, coll.length()), false); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromKeys(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.keysIterator()), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromValues(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.valuesIterator()), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, but + * note that this creates a new collection containing the Map's key-value pairs. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > from(scala.collection.Map coll) { + return StreamSupport.stream(new StepsAnyIterator< scala.Tuple2 >(coll.iterator()), false); + } + + /** + * Generates a Stream that traverses a scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.Iterator coll) { + return StreamSupport.stream(new StepsAnyIterator(coll), false); + } + + /** + * Generates a Stream that traverses a scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the fromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable + * + * @param coll The scala.collection.Iterable to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream from(scala.collection.Iterable coll) { + return StreamSupport.stream(new StepsAnyIterator(coll.iterator()), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll); + return StreamSupport.stream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.keysIterator()); + return StreamSupport.stream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream fromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.valuesIterator()); + return StreamSupport.stream(acc.spliterator(), false); + } + + //////////////////// + // Double Streams // + //////////////////// + + /** + * Generates a DoubleStream that traverses an IndexedSeq of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.doubleStream(new StepsDoubleIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.doubleStream(new StepsDoubleImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.doubleStream(new StepsDoubleImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.immutable.HashSet of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.doubleStream(new StepsDoubleImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a DoubleStream that traverses double-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses double-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.mutable.HashSet of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.doubleStream(new StepsDoubleFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a DoubleStream that traverses a scala.collection.immutable.Vector of Doubles. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.doubleStream(new StepsDoubleVector(erased, 0, coll.length()), false); + } + + /** + * Generates a DoubleStream that traverses the double-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a DoubleStream that traverses the double-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a DoubleStream that traverses a double-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.Iterator coll) { + return StreamSupport.doubleStream(new StepsDoubleIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a DoubleStream that traverses a double-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the doubleFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.DoubleAccumulator acc = + scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.doubleStream(acc.spliterator(), false); + } + + ///////////////// + // Int Streams // + ///////////////// + + /** + * Generates a IntStream that traverses a BitSet. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The BitSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.BitSet coll) { + // Let the value class figure out the casting! + scala.compat.java8.converterImpls.RichBitSetCanStep rbscs = + new scala.compat.java8.converterImpls.RichBitSetCanStep(coll); + return StreamSupport.intStream(rbscs.stepper(), false); + } + + /** + * Generates a IntStream that traverses a Range. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Range to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.Range coll) { + return StreamSupport.intStream(new scala.compat.java8.converterImpls.StepsIntRange(coll, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses an IndexedSeq of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.intStream(new StepsIntIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses int-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.intStream(new StepsIntImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a IntStream that traverses int-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.intStream(new StepsIntImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.immutable.HashSet of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.intStream(new StepsIntImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a IntStream that traverses int-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses int-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.mutable.HashSet of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.intStream(new StepsIntFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a IntStream that traverses a scala.collection.immutable.Vector of Ints. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.intStream(new StepsIntVector(erased, 0, coll.length()), false); + } + + /** + * Generates a IntStream that traverses the int-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a IntStream that traverses the int-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a IntStream that traverses a int-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.Iterator coll) { + return StreamSupport.intStream(new StepsIntIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a IntStream that traverses a int-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the intFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.intStream(new StepsIntIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.intStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.intStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static IntStream intFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.IntAccumulator acc = + scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.intStream(acc.spliterator(), false); + } + + ////////////////// + // Long Streams // + ////////////////// + + /** + * Generates a LongStream that traverses an IndexedSeq of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The IndexedSeq to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.IndexedSeq coll) { + return StreamSupport.longStream(new StepsLongIndexedSeq(coll, 0, coll.length()), false); + } + + /** + * Generates a LongStream that traverses long-valued keys of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.immutable.HashMap coll) { + return StreamSupport.longStream(new StepsLongImmHashMapKey(coll, 0, coll.size()), false); + } + + /** + * Generates a LongStream that traverses long-valued values of a scala.collection.immutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.immutable.HashMap coll) { + return StreamSupport.longStream(new StepsLongImmHashMapValue(coll, 0, coll.size()), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.immutable.HashSet of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The immutable.HashSet to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.immutable.HashSet coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.longStream(new StepsLongImmHashSet(iter, coll.size()), false); + } + + /** + * Generates a LongStream that traverses long-valued keys of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongHashTableKey(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses long-valued values of a scala.collection.mutable.HashMap. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashMap to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.mutable.HashMap coll) { + scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongDefaultHashTableValue(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.mutable.HashSet of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The mutable.HashSet to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.mutable.HashSet coll) { + Object[] tbl = CollectionInternals.getTable(coll); + return StreamSupport.longStream(new StepsLongFlatHashTable(tbl, 0, tbl.length), false); + } + + /** + * Generates a LongStream that traverses a scala.collection.immutable.Vector of Longs. + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The Vector to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.immutable.Vector coll) { + scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; + return StreamSupport.longStream(new StepsLongVector(erased, 0, coll.length()), false); + } + + /** + * Generates a LongStream that traverses the long-valued keys of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulatedKeys method instead, but + * note that this creates a new collection containing the Map's keys. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromKeys(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a LongStream that traverses the long-valued values of a scala.collection.Map. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulatedValues method instead, but + * note that this creates a new collection containing the Map's values. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromValues(scala.collection.Map coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a LongStream that traverses a long-valued scala.collection.Iterator. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterator. + * + * @param coll The scala.collection.Iterator to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.Iterator coll) { + return StreamSupport.longStream(new StepsLongIterator((scala.collection.Iterator)coll), false); + } + + /** + * Generates a LongStream that traverses a long-valued scala.collection.Iterable. + *

+ * Only sequential operations will be efficient. + * For efficient parallel operation, use the longFromAccumulated method instead, + * but note that this creates a copy of the contents of the Iterable. + * + * @param coll The scala.collection.Iterable to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFrom(scala.collection.Iterable coll) { + scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); + return StreamSupport.longStream(new StepsLongIterator(iter), false); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulated(scala.collection.TraversableOnce coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.TraversableOnce)coll); + return StreamSupport.longStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulatedKeys(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.keysIterator()); + return StreamSupport.longStream(acc.spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static LongStream longFromAccumulatedValues(scala.collection.Map coll) { + scala.compat.java8.collectionImpl.LongAccumulator acc = + scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); + return StreamSupport.longStream(acc.spliterator(), false); + } +} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index a6ae6d1..af24359 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -137,6 +137,10 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * * Scala collections gain extension methods `seqStream` and * `parStream` that allow them to be used as the source of a `Stream`. + * Some collections either intrinsically cannot be paralellized, or + * could be but an efficient implementation is missing. It this case, + * only `seqStream` is provided. If a collection cannot be stepped over + * at all (e.g. `Traversable`), then it gains neither method. * * `Array` also gains `seqStream` and `parStream` methods, and calling those * on `Array[Double]`, `Array[Int]`, or `Array[Long]` will produce the @@ -152,10 +156,32 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * have custom accumulators with improved performance. * * Accumulators have `toArray`, `toList`, `iterator`, and `to[_]` methods - * to convert to standard Scala collections. + * to convert to standard Scala collections. Note that if you wish to + * create an array from a `Stream`, going through an `Accumulator` is + * not the most efficient option: just create the `Array` directly. * - * Example: - * ``` + * Internally, Scala collections implement a hybrid of `Iterator` and + * `java.util.Spliterator` to implement `Stream` compatibility; these + * are called `Stepper`s. In particular, they can test for the presence + * of a next element using `hasStep`, can retrieve the next value with + * `nextStep`, or can optionally retrieve and operate on a value if present + * with `tryStep`, which works like `tryAdvance` in `java.util.Spliterator`. + * + * Every Scala collection that can be stepped + * through has a `stepper` method implicitly provided. In addition, + * maps have `keyStepper` and `valueStepper` methods. A limited number + * of collections operations are defined on `Stepper`s, including conversion + * to Scala collections with `to` or accumulation via `accumulate`. + * `Stepper`s also implement `seqStream` and `parStream` to generate `Stream`s. + * These are provided regardless of whether a `Stepper` can efficiently + * subdivide itself for parallel processing (though one can check for the + * presence of the `EfficientSubstep` trait to know that parallel execution will + * not be limited by long sequential searching steps, and one can call + * `anticipateParallelism` to warn a `Stepper` that it will be used in a parallel + * context and thus may wish to make different tradeoffs). + * + * Examples: + * {{{ * import scala.compat.java8.StreamConverers._ * * val s = Vector(1,2,3,4).parStream // Stream[Int] @@ -165,7 +191,9 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * * val t = Array(2.0, 3.0, 4.0).parStream // DoubleStream * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] - * ``` + * + * val x = List(1L, 2L, 3L, 4L).stepper.parStream.sum // 10, potentially computed in parallel + * }}} */ object StreamConverters extends Priority1StreamConverters @@ -273,4 +301,28 @@ with converterImpls.Priority1AccumulatorConverters } } } + + implicit val accumulateDoubleStepper = new AccumulatesFromStepper[Double, DoubleAccumulator] { + def apply(stepper: Stepper[Double]) = { + val a = new DoubleAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } + + implicit val accumulateIntStepper = new AccumulatesFromStepper[Int, IntAccumulator] { + def apply(stepper: Stepper[Int]) = { + val a = new IntAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } + + implicit val accumulateLongStepper = new AccumulatesFromStepper[Long, LongAccumulator] { + def apply(stepper: Stepper[Long]) = { + val a = new LongAccumulator + while (stepper.hasStep) a += stepper.nextStep + a + } + } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala index ae4e6fe..ed7105d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulates.scala @@ -5,6 +5,10 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ +trait AccumulatesFromStepper[@specialized(Double, Int, Long) A, Acc <: AccumulatorLike[A, Acc]] { + def apply(stepper: Stepper[A]): Acc +} + final class CollectionCanAccumulate[A](private val underlying: TraversableOnce[A]) extends AnyVal { def accumulate: Accumulator[A] = { val a = new Accumulator[A] diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala index b28790c..e67ca79 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -214,6 +214,13 @@ object Accumulator { /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]) { a1 drain a2 } } + + /** Builds an `Accumulator` from any `TraversableOnce` */ + def from[A](source: TraversableOnce[A]) = { + val a = new Accumulator[A] + source.foreach(a += _) + a + } } private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) extends AnyStepper[A] { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala index 1f44f97..7e95a69 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorConverters.scala @@ -2,6 +2,8 @@ package scala.compat.java8.converterImpls import language.implicitConversions +import scala.compat.java8.collectionImpl._ + trait Priority3AccumulatorConverters { implicit def collectionCanAccumulate[A](underlying: TraversableOnce[A]) = new CollectionCanAccumulate[A](underlying) } @@ -17,4 +19,17 @@ trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) + + implicit def accumulateAnyStepper[A]: AccumulatesFromStepper[A, Accumulator[A]] = + PrivateAccumulatorConverters.genericAccumulateAnyStepper.asInstanceOf[AccumulatesFromStepper[A, Accumulator[A]]] +} + +private[java8] object PrivateAccumulatorConverters { + val genericAccumulateAnyStepper: AccumulatesFromStepper[Any, Accumulator[Any]] = new AccumulatesFromStepper[Any, Accumulator[Any]] { + def apply(stepper: Stepper[Any]) = { + val a = new Accumulator[Any] + while (stepper.hasStep) a += stepper.nextStep + a + } + } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index 9703fe9..b99ba7d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -211,6 +211,13 @@ object DoubleAccumulator { /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator) { a1 drain a2 } } + + /** Builds a `DoubleAccumulator` from any `Double`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Double]) = { + val a = new DoubleAccumulator + source.foreach(a += _) + a + } } private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator) extends DoubleStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index 69a13d1..253119e 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -218,6 +218,13 @@ object IntAccumulator { /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator) { a1 drain a2 } } + + /** Builds an `IntAccumulator` from any `Int`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Int]) = { + val a = new IntAccumulator + source.foreach(a += _) + a + } } private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) extends IntStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 8cf770c..270d400 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -212,6 +212,13 @@ object LongAccumulator { /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator) { a1 drain a2 } } + + /** Builds a `LongAccumulator` from any `Long`-valued `TraversableOnce` */ + def from[A](source: TraversableOnce[Long]) = { + val a = new LongAccumulator + source.foreach(a += _) + a + } } private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) extends LongStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index cc5a5bc..8963462 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -36,7 +36,14 @@ import java.util.Spliterator * println(s.hasStep) // Prints `false` * }}} */ -trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] {} +trait Stepper[@specialized(Double, Int, Long) A] extends StepperLike[A, Stepper[A]] { + /** Drains the contents of this stepper into an `Accumulator` or specialized variant thereof as appropriate. + * This is a terminal operation. + * + * Note: accumulation will occur sequentially. To accumulate in parallel, use a `Stream` (i.e. `.parStream.accumulate`). + */ + def accumulate[Acc <: AccumulatorLike[A, Acc]](implicit accer: scala.compat.java8.converterImpls.AccumulatesFromStepper[A, Acc]) = accer(this) +} /** An (optional) marker trait that indicates that a `Stepper` can call `substep` with * at worst O(log N) time and space complexity, and that the division is likely to @@ -159,6 +166,13 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => def hasNext = self.hasStep def next = self.nextStep } + + /** Returns a Scala collection of the type requested. */ + def to[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, A, Coll[A]]): Coll[A] = { + val b = cbf() + while (hasStep) b += nextStep + b.result() + } } From 86370b046bdbfc86a8f6dccd121e9e1e90ded372 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Tue, 1 Dec 2015 18:29:38 -0800 Subject: [PATCH 072/340] Reorganized namespaces for Stream compatibility. Basically, everything to do with conversion is in conversionImpl, while actual collection classes are in collectionImpl. Most everything in here should be private[java8], but it probably isn't yet. --- .../java/scala/compat/java8/ScalaStreaming.java | 9 +++++---- .../scala/compat/java8/StreamConverters.scala | 6 +++--- .../compat/java8/collectionImpl/Stepper.scala | 2 +- .../Accumulates.scala | 2 +- .../AccumulatorConverters.scala | 2 +- .../MakesSteppers.scala | 2 +- .../{ => converterImpl}/StepConverters.scala | 2 +- .../StepsArray.scala | 2 +- .../StepsBitSet.scala | 2 +- .../StepsFlatHashTable.scala | 2 +- .../StepsHashTable.scala | 2 +- .../StepsImmHashMap.scala | 2 +- .../StepsImmHashSet.scala | 2 +- .../StepsIndexedSeq.scala | 2 +- .../StepsIterable.scala | 2 +- .../StepsIterator.scala | 2 +- .../StepsLikeGapped.scala | 13 +++++++------ .../StepsLikeImmHashMap.scala | 14 ++++++++------ .../StepsLikeIndexed.scala | 14 ++++++++------ .../StepsLikeIterator.scala | 14 ++++++++------ .../StepsLikeSliced.scala | 14 ++++++++------ .../StepsLikeTrieIterator.scala | 17 +++++++++-------- .../StepsLinearSeq.scala | 2 +- .../StepsMap.scala | 2 +- .../StepsRange.scala | 2 +- .../StepsString.scala | 2 +- .../StepsVector.scala | 2 +- .../StepsWithTail.scala | 13 +++++++------ .../scala/compat/java8/StepConvertersTest.scala | 1 + 29 files changed, 83 insertions(+), 70 deletions(-) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/Accumulates.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/AccumulatorConverters.scala (97%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/MakesSteppers.scala (99%) rename src/main/scala/scala/compat/java8/{ => converterImpl}/StepConverters.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsArray.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsBitSet.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsFlatHashTable.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsHashTable.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsImmHashMap.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsImmHashSet.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIndexedSeq.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIterable.scala (96%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsIterator.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeGapped.scala (74%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeImmHashMap.scala (66%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeIndexed.scala (65%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeIterator.scala (81%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeSliced.scala (67%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLikeTrieIterator.scala (61%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsLinearSeq.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsMap.scala (97%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsRange.scala (98%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsString.scala (96%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsVector.scala (99%) rename src/main/scala/scala/compat/java8/{collectionImpl => converterImpl}/StepsWithTail.scala (79%) diff --git a/src/main/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreaming.java index b32ae32..9367361 100644 --- a/src/main/java/scala/compat/java8/ScalaStreaming.java +++ b/src/main/java/scala/compat/java8/ScalaStreaming.java @@ -1,6 +1,7 @@ package scala.compat.java8; -import scala.compat.java8.converterImpls.*; +import scala.compat.java8.converterImpl.*; +import scala.compat.java8.collectionImpl.*; import java.util.stream.*; import scala.compat.java8.runtime.CollectionInternals; @@ -471,8 +472,8 @@ public static DoubleStream doubleFromAccumulatedValues(scala.collection.Map: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { protected var currentEntry: AnyRef = null def semiclone(half: Int): Semi def characteristics(): Int = Ordered @@ -33,7 +34,7 @@ abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val u /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` * and interpreting the contents as the elements of a collection. */ -abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] with EfficientSubstep @@ -43,7 +44,7 @@ abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underly * and interpreting the contents as the elements of a collection of `Double`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextDouble`. */ -abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) with DoubleStepper with EfficientSubstep @@ -53,7 +54,7 @@ abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_u * and interpreting the contents as the elements of a collection of `Int`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextInt`. */ -abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) with IntStepper with EfficientSubstep @@ -63,7 +64,7 @@ abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underly * and interpreting the contents as the elements of a collection of `Long`s. Subclasses * are responsible for unboxing the `AnyRef` inside `nextLong`. */ -abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala similarity index 66% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala index 169991c..6f4d0c9 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -1,13 +1,15 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over an immutable HashMap by slicing it into pieces. * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the * collection needs some sort of modification before transmission to the subclass. */ -trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] +private[java8] trait AbstractStepsLikeImmHashMap[K, V, A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeImmHashMap[K, V, A, Sub, _]] extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { protected var theIterator: Iterator[A] = null protected def demiclone(u: collection.immutable.HashMap[K,V], j0: Int, jN: Int): Semi @@ -32,22 +34,22 @@ extends AbstractStepsLikeSliced[collection.immutable.HashMap[K, V], Sub, Semi] { } } -abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeImmHashMap[K, V, A, SIHM >: Null <: StepsLikeImmHashMap[K, V, A, _]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLikeSliced[A, collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, A, AnyStepper[A], SIHM] {} -abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeImmHashMap[K, V, SIHM >: Null <: StepsDoubleLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsDoubleLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Double, DoubleStepper, SIHM] {} -abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeImmHashMap[K, V, SIHM >: Null <: StepsIntLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsIntLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Int, IntStepper, SIHM] {} -abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeImmHashMap[K, V, SIHM >: Null <: StepsLongLikeImmHashMap[K, V, SIHM]](_underlying: collection.immutable.HashMap[K, V], _i0: Int, _iN: Int) extends StepsLongLikeSliced[collection.immutable.HashMap[K, V], SIHM](_underlying, _i0, _iN) with AbstractStepsLikeImmHashMap[K, V, Long, LongStepper, SIHM] {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala similarity index 65% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index 6a55395..175cf0d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -1,10 +1,12 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over an indexable collection */ -abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { def semiclone(half: Int): Semi def characteristics(): Int = Ordered + Sized + SubSized def estimateSize(): Long = iN - i0 @@ -21,28 +23,28 @@ abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) +private[java8] abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala similarity index 81% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala index 972b989..116e921 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -1,10 +1,12 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Common functionality for Steppers that step through an Iterator, caching the results as needed when a split is requested. */ -abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { +private[java8] abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP](final protected var underlying: Iterator[A]) { final protected var nextChunkSize = 16 final protected var proxied: SP = null def semiclone(): Semi // Must initialize with null iterator! @@ -14,7 +16,7 @@ abstract class AbstractStepsLikeIterator[A, SP >: Null <: Stepper[A], Semi <: SP } /** Abstracts the operation of stepping over an iterator (that needs to be cached when splitting) */ -abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) +private[java8] abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] with AnyStepper[A]](_underlying: Iterator[A]) extends AbstractStepsLikeIterator[A, AnyStepper[A], SLI](_underlying) with AnyStepper[A] { @@ -37,7 +39,7 @@ abstract class StepsLikeIterator[A, SLI >: Null <: StepsLikeIterator[A, SLI] wit } /** Abstracts the operation of stepping over an iterator of Doubles (needs caching when split) */ -abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) +private[java8] abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SLI] with DoubleStepper](_underlying: Iterator[Double]) extends AbstractStepsLikeIterator[Double, DoubleStepper, SLI](_underlying) with DoubleStepper { @@ -60,7 +62,7 @@ abstract class StepsDoubleLikeIterator[SLI >: Null <: StepsDoubleLikeIterator[SL } /** Abstracts the operation of stepping over an iterator of Ints (needs caching when split) */ -abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) +private[java8] abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] with IntStepper](_underlying: Iterator[Int]) extends AbstractStepsLikeIterator[Int, IntStepper, SLI](_underlying) with IntStepper { @@ -83,7 +85,7 @@ abstract class StepsIntLikeIterator[SLI >: Null <: StepsIntLikeIterator[SLI] wit } /** Abstracts the operation of stepping over an iterator of Longs (needs caching when split) */ -abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) +private[java8] abstract class StepsLongLikeIterator[SLI >: Null <: StepsLongLikeIterator[SLI] with LongStepper](_underlying: Iterator[Long]) extends AbstractStepsLikeIterator[Long, LongStepper, SLI](_underlying) with LongStepper { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala similarity index 67% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala index d7a1fdb..4ec9b74 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -1,13 +1,15 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a collection that can be sliced into pieces. * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the * collection needs some sort of modification before transmission to the subclass. */ -abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { protected var i0: Int = i def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! def characteristics(): Int = Ordered @@ -16,28 +18,28 @@ abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected } /** Abstracts the operation of stepping over a generic collection that can be efficiently sliced or otherwise subdivided */ -abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ -abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) with DoubleStepper with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ -abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) with IntStepper with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ -abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) +private[java8] abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) with LongStepper with EfficientSubstep diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala similarity index 61% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala index 631ed11..6565dd8 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLikeTrieIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -1,20 +1,21 @@ -package scala.compat.java8 -package collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator + +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a TrieIterator by asking itself to * slice itself into pieces. Note that `i` must be kept up to date in subclasses. */ -trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] +private[java8] trait AbstractStepsLikeTrieIterator[A, Sub >: Null, Semi >: Null <: Sub with AbstractStepsLikeTrieIterator[A, Sub, _]] extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { protected def demiclone(it: Iterator[A], N: Int): Semi override def characteristics() = Immutable def hasNext(): Boolean = underlying.hasNext def semiclone(halfHint: Int): Semi = if (!underlying.hasNext || i > iN-2) null - else runtime.CollectionInternals.trieIteratorSplit(underlying) match { + else scala.compat.java8.runtime.CollectionInternals.trieIteratorSplit(underlying) match { case null => null case ((pre: Iterator[A], pno), post: Iterator[A]) => val pn = (pno: Any) match { case i: Int => i; case _ => throw new Exception("Unexpected type") } @@ -27,22 +28,22 @@ extends AbstractStepsLikeSliced[Iterator[A], Sub, Semi] { } } -abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) +private[java8] abstract class StepsLikeTrieIterator[A, STI >: Null <: StepsLikeTrieIterator[A, _]](_underlying: Iterator[A], _N: Int) extends StepsLikeSliced[A, Iterator[A], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[A, AnyStepper[A], STI] {} -abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) +private[java8] abstract class StepsDoubleLikeTrieIterator[STI >: Null <: StepsDoubleLikeTrieIterator[STI]](_underlying: Iterator[Double], _N: Int) extends StepsDoubleLikeSliced[Iterator[Double], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Double, DoubleStepper, STI] {} -abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) +private[java8] abstract class StepsIntLikeTrieIterator[STI >: Null <: StepsIntLikeTrieIterator[STI]](_underlying: Iterator[Int], _N: Int) extends StepsIntLikeSliced[Iterator[Int], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Int, IntStepper, STI] {} -abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) +private[java8] abstract class StepsLongLikeTrieIterator[STI >: Null <: StepsLongLikeTrieIterator[STI]](_underlying: Iterator[Long], _N: Int) extends StepsLongLikeSliced[Iterator[Long], STI](_underlying, 0, _N) with AbstractStepsLikeTrieIterator[Long, LongStepper, STI] {} diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala similarity index 98% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index e809424..d310560 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala similarity index 97% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index fcaaa67..e5c072b 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala similarity index 98% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index 1eb1282..bde77dc 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala similarity index 96% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index d3bccc0..a281068 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala similarity index 99% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index 12923c9..e3188f0 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,4 +1,4 @@ -package scala.compat.java8.converterImpls +package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala similarity index 79% rename from src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala rename to src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala index 464880b..0fcc12b 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/StepsWithTail.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -1,6 +1,7 @@ -package scala.compat.java8.collectionImpl +package scala.compat.java8.converterImpl import java.util.Spliterator +import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over a collection with a fast tail operation. @@ -10,7 +11,7 @@ import Stepper._ * * Subclasses MUST decrement `maxN` when consuming elements, or this will not work! */ -abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { +private[java8] abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final protected var underlying: CC, final protected var maxN: Long) { private var nextChunkSize: Int = 0 protected def myIsEmpty(cc: CC): Boolean protected def myTailOf(cc: CC): CC @@ -62,25 +63,25 @@ abstract class AbstractStepsWithTail[CC >: Null, Sub >: Null, Semi <: Sub](final } /** Abstracts the operation of stepping over a generic indexable collection */ -abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsWithTail[A, CC >: Null, STA >: Null <: StepsWithTail[A, CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, AnyStepper[A], STA](_underlying, _maxN) with AnyStepper[A] {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ -abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsDoubleWithTail[CC >: Null, STD >: Null <: StepsDoubleWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, DoubleStepper, STD](_underlying, _maxN) with DoubleStepper {} /** Abstracts the operation of stepping over an indexable collection of Ints */ -abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsIntWithTail[CC >: Null, STI >: Null <: StepsIntWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, IntStepper, STI](_underlying, _maxN) with IntStepper {} /** Abstracts the operation of stepping over an indexable collection of Longs */ -abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) +private[java8] abstract class StepsLongWithTail[CC >: Null, STL >: Null <: StepsLongWithTail[CC, _]](_underlying: CC, _maxN: Long) extends AbstractStepsWithTail[CC, LongStepper, STL](_underlying, _maxN) with LongStepper {} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index ac18a7c..2f09927 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -6,6 +6,7 @@ import org.junit.Assert._ class StepConvertersTest { import java.util._ import collectionImpl._ + import converterImpl._ import StreamConverters._ // Includes StepConverters! import scala.{ collection => co } import collection.{ mutable => cm, immutable => ci, concurrent => cc } From e77ca8724986895acaa594114ac2458db5ccfa45 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 5 Dec 2015 16:41:50 -0800 Subject: [PATCH 073/340] Adding benchmarking: made generators for collections. Also retrofitted stream converters so you can use them generically. --- benchmark/build.sbt | 10 +++ benchmark/project/plugins.sbt | 1 + .../main/scala/bench/CollectionSource.scala | 68 +++++++++++++++++++ .../scala/compat/java8/StreamConverters.scala | 33 ++++++--- .../java8/converterImpl/MakesSteppers.scala | 10 +++ 5 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 benchmark/build.sbt create mode 100644 benchmark/project/plugins.sbt create mode 100644 benchmark/src/main/scala/bench/CollectionSource.scala diff --git a/benchmark/build.sbt b/benchmark/build.sbt new file mode 100644 index 0000000..5365275 --- /dev/null +++ b/benchmark/build.sbt @@ -0,0 +1,10 @@ +enablePlugins(JmhPlugin) + +lazy val root = (project in file(".")).settings( + name := "java8-compat-bench", + scalaVersion := "2.11.7", + crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), + organization := "org.scala-lang.modules", + version := "0.6.0-SNAPSHOT", + unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.6.0-SNAPSHOT.jar") +) diff --git a/benchmark/project/plugins.sbt b/benchmark/project/plugins.sbt new file mode 100644 index 0000000..d85fed8 --- /dev/null +++ b/benchmark/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.4") diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala new file mode 100644 index 0000000..4c01c7d --- /dev/null +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -0,0 +1,68 @@ +package bench + +import java.util.stream._ + +import scala.collection.generic.CanBuildFrom +import scala.compat.java8.StreamConverters._ +import scala.compat.java8.collectionImpl._ +import scala.compat.java8.converterImpl._ + +package object generate { + private def myInty(n: Int) = 0 until n + private def myStringy(n: Int) = myInty(n).map(i => (i*i).toString) + + object Coll { + def i[CC[_]](n: Int)(implicit cbf: CanBuildFrom[Nothing, Int, CC[Int]]): CC[Int] = { + val b = cbf(); + myInty(n).foreach(b += _) + b.result() + } + def s[CC[_]](n: Int)(implicit cbf: CanBuildFrom[Nothing, String, CC[String]]): CC[String] = { + val b = cbf(); + myStringy(n).foreach(b += _) + b.result() + } + } + + object Pstep { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStepper = + steppize(cc).stepper + def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): AnyStepper[String] = + steppize(cc).stepper + } + + object Sstep { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStepper = + steppize(cc).stepper + def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): AnyStepper[String] = + steppize(cc).stepper + } + + object PsStream { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStream = + steppize(cc).stepper.parStream + def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): Stream[String] = + steppize(cc).stepper.parStream + } + + object SsStream { + def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStream = + steppize(cc).stepper.seqStream + def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): Stream[String] = + steppize(cc).stepper.seqStream + } + + object Sstream { + def i[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[java.lang.Integer, IntStream]) = + streamize(cc).seqStream + def s[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[String, Stream[String]]) = + streamize(cc).seqStream + } + + object Pstream { + def i[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[java.lang.Integer, IntStream]) = + streamize(cc).parStream + def s[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[String, Stream[String]]) = + streamize(cc).parStream + } +} diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 9efc805..3999761 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -16,7 +16,8 @@ trait PrimitiveStreamUnboxer[A, S] { trait Priority5StreamConverters { // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. - implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) { + implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) + extends MakesSequentialStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeySeqStepper[K]) { @@ -28,13 +29,16 @@ trait Priority5StreamConverters { } trait Priority4StreamConverters extends Priority5StreamConverters { - implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) { + implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) + extends MakesSequentialStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) { + implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) + extends MakesSequentialStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) { + implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) + extends MakesSequentialStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeySeqStepper) { @@ -58,7 +62,8 @@ trait Priority4StreamConverters extends Priority5StreamConverters { } trait Priority3StreamConverters extends Priority4StreamConverters { - implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) { + implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) + extends MakesSequentialStream[A, Stream[A]] with MakesParallelStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) } @@ -73,7 +78,8 @@ trait Priority3StreamConverters extends Priority4StreamConverters { } trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) { + implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) + extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -85,7 +91,8 @@ trait Priority2StreamConverters extends Priority3StreamConverters { def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) { + implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) + extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -97,7 +104,8 @@ trait Priority2StreamConverters extends Priority3StreamConverters { def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) { + implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) + extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) } @@ -200,17 +208,20 @@ extends Priority1StreamConverters with converterImpl.Priority1StepConverters with converterImpl.Priority1AccumulatorConverters { - implicit class EnrichDoubleArrayWithStream(a: Array[Double]) { + implicit class EnrichDoubleArrayWithStream(a: Array[Double]) + extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel } - implicit class EnrichIntArrayWithStream(a: Array[Int]) { + implicit class EnrichIntArrayWithStream(a: Array[Int]) + extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = java.util.Arrays.stream(a) def parStream: IntStream = seqStream.parallel } - implicit class EnrichLongArrayWithStream(a: Array[Long]) { + implicit class EnrichLongArrayWithStream(a: Array[Long]) + extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = java.util.Arrays.stream(a) def parStream: LongStream = seqStream.parallel } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index ed315a8..ed7607d 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -5,6 +5,16 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ +/** Classes or objects implementing this trait create streams suitable for sequential use */ +trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { + def seqStream: SS +} + +/** Classes or objects implementing this trait create streams suitable for parallel use */ +trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { + def parStream: SS +} + /** Classes or objects implementing this trait create generic steppers suitable for sequential use. */ trait MakesAnySeqStepper[A] extends Any { /** Generates a fresh stepper over `A`s suitable for sequential use */ From 970278cc9a837043898b8a10dd6f2a1a1d1f3745 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 7 Dec 2015 16:49:31 -0800 Subject: [PATCH 074/340] Create a bunch of classes for benchmarking. Code is quite general, since compiler can be tricked into expanding everything the way it needs to be. --- .../main/scala/bench/CollectionSource.scala | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 4c01c7d..9f63422 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -65,4 +65,106 @@ package object generate { def s[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[String, Stream[String]]) = streamize(cc).parStream } + + trait GenThingsOf[CC[_]] { + def title: String + def sizes: Array[Int] + } + + trait IntThingsOf[CC[_]] extends GenThingsOf[CC] { + implicit def myCBFi: CanBuildFrom[Nothing, Int, CC[Int]] + // Base collection + val cI = sizes.map(n => Coll.i[CC](n)) + // Iterator + def iI(j: Int)(implicit x: CC[Int] => Iterator[Int]) = x(cI(j)) + // Steppers (second letter--s = sequential, p = parallel) + def tsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = Sstep i cI(j) + def tpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = Pstep i cI(j) + // Streams + def ssI(j: Int)(implicit x: CC[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = Sstream i cI(j) + def spI(j: Int)(implicit x: CC[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = Pstream i cI(j) + // Streams via steppers + def zsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = SsStream i cI(j) + def zpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = PsStream i cI(j) + } + + trait StringThingsOf[CC[_]] extends GenThingsOf[CC] { + implicit def myCBFs: CanBuildFrom[Nothing, String, CC[String]] + // Base collection + val cS = sizes.map(n => Coll.s[CC](n)) + // Iterator + def iS(j: Int)(implicit x: CC[String] => Iterator[String]) = x(cS(j)) + // Steppers (second letter--s = sequential, p = parallel) + def tsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = Sstep s cS(j) + def tpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = Pstep s cS(j) + // Streams + def ssS(j: Int)(implicit x: CC[String] => MakesSequentialStream[String, Stream[String]]) = Sstream s cS(j) + def spS(j: Int)(implicit x: CC[String] => MakesParallelStream[String, Stream[String]]) = Pstream s cS(j) + // Streams via steppers + def zsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = SsStream s cS(j) + def zpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = PsStream s cS(j) + } + + trait ThingsOf[CC[_]] extends IntThingsOf[CC] with StringThingsOf[CC] {} + + abstract class AbstractThings[CC[_]](val title: String)( + implicit + outerCBFi: CanBuildFrom[Nothing, Int, CC[Int]], + outerCBFs: CanBuildFrom[Nothing, String, CC[String]] + ) + extends ThingsOf[CC] { + implicit def myCBFi = outerCBFi + implicit def myCBFs = outerCBFs + } + + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} + + class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} + + class LstThings(val sizes: Array[Int]) extends AbstractThings[List]("List") {} + + class IlsThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.ListSet]("immutable.ListSet") {} + + class QueThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.Queue]("immutable.Queue") {} + + class StmThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.Stream]("immutable.Stream") {} + + class TrsThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.TreeSet]("immutable.TreeSet") {} + + class VecThings(val sizes: Array[Int]) extends AbstractThings[Vector]("Vector") {} + + class ArbThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArrayBuffer]("mutable.ArrayBuffer") {} + + class ArsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArraySeq]("mutable.ArraySeq") {} + + class AstThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.ArrayStack]("mutable.ArrayStack") {} + + class MhsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.HashSet]("mutable.HashSet") {} + + class LhsThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.LinkedHashSet]("mutable.LinkedHashSet") {} + + class PrqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.PriorityQueue]("mutable.PriorityQueue") {} + + class MuqThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.Queue]("mutable.Queue") {} + + class WraThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.WrappedArray]("mutable.WrappedArray") {} + + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { + lazy val arr = new ArrThings(sizes) + lazy val ish = new IshThings(sizes) + lazy val lst = new LstThings(sizes) + lazy val ils = new IlsThings(sizes) + lazy val que = new QueThings(sizes) + lazy val stm = new StmThings(sizes) + lazy val trs = new TrsThings(sizes) + lazy val vec = new VecThings(sizes) + lazy val arb = new ArbThings(sizes) + lazy val ars = new ArsThings(sizes) + lazy val ast = new AstThings(sizes) + lazy val mhs = new MhsThings(sizes) + lazy val lhs = new LhsThings(sizes) + lazy val prq = new PrqThings(sizes) + lazy val muq = new MuqThings(sizes) + lazy val wra = new WraThings(sizes) + } } From 82ec9a518f825b4d3e314898ef751b50e990fc4f Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 19 Dec 2015 20:56:46 -0800 Subject: [PATCH 075/340] Finished Java collection stream typeclasses. Writing code generator for tests. --- benchmark/src/main/scala/bench/CodeGen.scala | 27 +++++ .../main/scala/bench/CollectionSource.scala | 103 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 benchmark/src/main/scala/bench/CodeGen.scala diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala new file mode 100644 index 0000000..90bbaa4 --- /dev/null +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -0,0 +1,27 @@ +package bench.codegen + +import scala.util._ +import scala.util.control.NonFatal + +object Generator { + val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { + try { + val pw = new java.io.PrintWriter(f) + val wr: String => Unit = s => pw.println(s) + try { pr(wr); Right(()) } + catch { case NonFatal(t) => Left(t) } + finally { pw.close() } + } + catch { case NonFatal(t) => Left(t) } + } + def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + Seq("test").foreach(pr) + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } +} diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 9f63422..5ddf263 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -117,6 +117,103 @@ package object generate { implicit def myCBFs = outerCBFs } + // Java collection CBFs + + implicit val javaUtilArrayListIntCanBuildFrom = new CanBuildFrom[Nothing, Int, java.util.ArrayList[Int]] { + def apply(from: Nothing): collection.mutable.Builder[Int, java.util.ArrayList[Int]] = apply() + def apply(): collection.mutable.Builder[Int, java.util.ArrayList[Int]] = new collection.mutable.Builder[Int, java.util.ArrayList[Int]] { + private var myAL = new java.util.ArrayList[Int] + def clear() = { myAL = new java.util.ArrayList[Int]; () } + def result() = { val ans = myAL; clear(); ans } + def +=(x: Int) = { myAL add x; this } + } + } + implicit val javaUtilArrayListStringCanBuildFrom = new CanBuildFrom[Nothing, String, java.util.ArrayList[String]] { + def apply(from: Nothing): collection.mutable.Builder[String, java.util.ArrayList[String]] = apply() + def apply(): collection.mutable.Builder[String, java.util.ArrayList[String]] = new collection.mutable.Builder[String, java.util.ArrayList[String]] { + private var myAL = new java.util.ArrayList[String] + def clear() = { myAL = new java.util.ArrayList[String]; () } + def result() = { val ans = myAL; clear(); ans } + def +=(x: String) = { myAL add x; this } + } + } + implicit val javaUtilLinkedListIntCanBuildFrom = new CanBuildFrom[Nothing, Int, java.util.LinkedList[Int]] { + def apply(from: Nothing): collection.mutable.Builder[Int, java.util.LinkedList[Int]] = apply() + def apply(): collection.mutable.Builder[Int, java.util.LinkedList[Int]] = new collection.mutable.Builder[Int, java.util.LinkedList[Int]] { + private var myLL = new java.util.LinkedList[Int] + def clear() = { myLL = new java.util.LinkedList[Int]; () } + def result() = { val ans = myLL; clear(); ans } + def +=(x: Int) = { myLL add x; this } + } + } + implicit val javaUtilLinkedListStringCanBuildFrom = new CanBuildFrom[Nothing, String, java.util.LinkedList[String]] { + def apply(from: Nothing): collection.mutable.Builder[String, java.util.LinkedList[String]] = apply() + def apply(): collection.mutable.Builder[String, java.util.LinkedList[String]] = new collection.mutable.Builder[String, java.util.LinkedList[String]] { + private var myLL = new java.util.LinkedList[String] + def clear() = { myLL = new java.util.LinkedList[String]; () } + def result() = { val ans = myLL; clear(); ans } + def +=(x: String) = { myLL add x; this } + } + } + + // Streams from ArrayList (Java) + + implicit val getsParStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { + new MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = ali. + asInstanceOf[java.util.ArrayList[java.lang.Integer]]. + parallelStream.parallel. + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsSeqStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { + new MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = ali. + asInstanceOf[java.util.ArrayList[java.lang.Integer]]. + stream(). + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsParStreamFromArrayListString: (java.util.ArrayList[String] => MakesParallelStream[String, Stream[String]]) = als => { + new MakesParallelStream[String, Stream[String]] { + def parStream: Stream[String] = als.parallelStream.parallel + } + } + implicit val getsSeqStreamFromArrayListString: (java.util.ArrayList[String] => MakesSequentialStream[String, Stream[String]]) = als => { + new MakesSequentialStream[String, Stream[String]] { + def seqStream: Stream[String] = als.stream + } + } + + // Streams from LinkedList (Java) + + implicit val getsParStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { + new MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = ali. + asInstanceOf[java.util.LinkedList[java.lang.Integer]]. + parallelStream.parallel. + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsSeqStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { + new MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = ali. + asInstanceOf[java.util.LinkedList[java.lang.Integer]]. + stream(). + mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) + } + } + implicit val getsParStreamFromLinkedListString: (java.util.LinkedList[String] => MakesParallelStream[String, Stream[String]]) = als => { + new MakesParallelStream[String, Stream[String]] { + def parStream: Stream[String] = als.parallelStream.parallel + } + } + implicit val getsSeqStreamFromLinkedListString: (java.util.LinkedList[String] => MakesSequentialStream[String, Stream[String]]) = als => { + new MakesSequentialStream[String, Stream[String]] { + def seqStream: Stream[String] = als.stream + } + } + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} @@ -149,6 +246,10 @@ package object generate { class WraThings(val sizes: Array[Int]) extends AbstractThings[collection.mutable.WrappedArray]("mutable.WrappedArray") {} + class JixThings(val sizes: Array[Int]) extends AbstractThings[java.util.ArrayList]("java.util.ArrayList") {} + + class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) @@ -166,5 +267,7 @@ package object generate { lazy val prq = new PrqThings(sizes) lazy val muq = new MuqThings(sizes) lazy val wra = new WraThings(sizes) + lazy val jix = new JixThings(sizes) + lazy val jln = new JlnThings(sizes) } } From 021490bce129cf5f521a6f2929b4607ec109e501 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Mon, 21 Dec 2015 20:38:25 -0800 Subject: [PATCH 076/340] Got a little more of the code gen framework written. --- benchmark/src/main/scala/bench/CodeGen.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 90bbaa4..a4d2dfb 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -5,6 +5,7 @@ import scala.util.control.NonFatal object Generator { val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { val pw = new java.io.PrintWriter(f) @@ -15,10 +16,21 @@ object Generator { } catch { case NonFatal(t) => Left(t) } } + + def sayArrayI(oa: Option[Array[Int]]) = oa match { case Some(a) => a.mkString("Array(", ",", ")"); case _ => "" } + def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - Seq("test").foreach(pr) + pr("""package bench.test""") + pr("""""") + pr("""object Agreement {""") + pr(""" def run() {""") + pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") + pr(""" def check[A](a1: A, a2: A, msg: String) = if (a1 != a2) wrong += msg""") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr(""" }""") + pr("""}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => From 733a0353371b83c310a070f4e13f2d920bfe79f8 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Thu, 31 Dec 2015 17:46:36 -0800 Subject: [PATCH 077/340] Starting to fill in code generators. Have basic correctness test several. --- benchmark/src/main/scala/bench/CodeGen.scala | 30 +++++++++++++++++-- .../main/scala/bench/CollectionSource.scala | 14 ++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index a4d2dfb..94ecefe 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -4,7 +4,9 @@ import scala.util._ import scala.util.control.NonFatal object Generator { - val names = "arr ish lst ils que stm trs vec arb ars ast mhs lhs prq muq wra jix jln".split(' ') + val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') + val names = annotated.map(_.takeWhile(_.isLetter)) + val nojnames = names.filterNot(_ startsWith "j") def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -20,15 +22,39 @@ object Generator { def sayArrayI(oa: Option[Array[Int]]) = oa match { case Some(a) => a.mkString("Array(", ",", ")"); case _ => "" } def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { + val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => pr("""package bench.test""") pr("""""") + pr("""import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr("""import scala.compat.java8.StreamConverters._""") + pr("""""") pr("""object Agreement {""") pr(""" def run() {""") pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") - pr(""" def check[A](a1: A, a2: A, msg: String) = if (a1 != a2) wrong += msg""") + pr(""" def check[A](a1: A, a2: => A, msg: String) {""") + pr(""" var t = System.nanoTime""") + pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans})) wrong += msg""") + pr(""" if (t > 2000000000) wrong += "Slow " + msg""") + pr(""" }""") pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr(""" for (i <- 0 until x.N) {""") + pr(""" val si = OnInt.sum(x.arr.cI(i))""") + nojnames.tail.foreach{ n => + pr( s" check(si, OnInt.sum(x.$n.cI(i)), ${q}cI sum $n ${q}+i.toString)") + } + nojnames.foreach{ n => + pr( s" check(si, OnInt.sum(x.$n.iI(i)), ${q}iI sum $n ${q}+i.toString)") + } + annotated.foreach{ m => + val n = m.takeWhile(_.isLetter) + val c = if (m contains "*") "ssI" else "spI" + pr( s" check(si, OnInt.sum(x.$n.$c(i)), ${q}$c sum $n ${q}+i.toString)") + } + pr( s" }") + pr(""" wrong.foreach(println)""") + pr(""" if (wrong.nonEmpty) sys.exit(1) """) pr(""" }""") pr("""}""") } match { diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 5ddf263..db8e4e4 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -214,6 +214,17 @@ package object generate { } } + object EnableIterators { + implicit val iterableIntToIterator: (Iterable[Int] => Iterator[Int]) = _.iterator + implicit val iterableStringToIterator: (Iterable[String] => Iterator[String]) = _.iterator + implicit val arrayIntToIterator: (Array[Int] => Iterator[Int]) = (a: Array[Int]) => new Iterator[Int] { + private[this] var i = 0 + def hasNext = i < a.length + def next = if (hasNext) { var ans = a(i); i += 1; ans } else throw new NoSuchElementException(i.toString) + } + implicit val arrayStringToIterator: (Array[String] => Iterator[String]) = _.iterator + } + class ArrThings(val sizes: Array[Int]) extends AbstractThings[Array]("Array") {} class IshThings(val sizes: Array[Int]) extends AbstractThings[collection.immutable.HashSet]("immutable.HashSet") {} @@ -250,7 +261,8 @@ package object generate { class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} - class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 50000, 200000, 1000000)) { + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 20000, 50000, 200000)) { + def N = sizes.length lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) lazy val lst = new LstThings(sizes) From 75a625df34cd8b15dace807c358ebc3f866d0537 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 1 Jan 2016 19:54:18 -0800 Subject: [PATCH 078/340] Generator for correctness almost complete. Still some differences between algorithms for different methods, so results aren't actually identical yet. (May need to intercept sets differently also.) --- benchmark/src/main/scala/bench/CodeGen.scala | 52 +++++++++++++------ .../main/scala/bench/CollectionSource.scala | 2 +- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 94ecefe..43623e3 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -1,12 +1,17 @@ package bench.codegen import scala.util._ -import scala.util.control.NonFatal +import control.NonFatal object Generator { val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc")) + def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { case Array(x) => (x, None); case Array(x,y) => (x, Some(y)) }) + val names = annotated.map(_.takeWhile(_.isLetter)) - val nojnames = names.filterNot(_ startsWith "j") + val nojname = names.filterNot(_ startsWith "j").toSet + val parname = annotated.filter(_.forall(_.isLetter)).toSet + val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -35,24 +40,39 @@ object Generator { pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") pr(""" def check[A](a1: A, a2: => A, msg: String) {""") pr(""" var t = System.nanoTime""") - pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans})) wrong += msg""") + pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr(""" wrong += msg""") pr(""" if (t > 2000000000) wrong += "Slow " + msg""") pr(""" }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + pr( s" { // Scope for operations $o collection $n") pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) - pr(""" for (i <- 0 until x.N) {""") - pr(""" val si = OnInt.sum(x.arr.cI(i))""") - nojnames.tail.foreach{ n => - pr( s" check(si, OnInt.sum(x.$n.cI(i)), ${q}cI sum $n ${q}+i.toString)") - } - nojnames.foreach{ n => - pr( s" check(si, OnInt.sum(x.$n.iI(i)), ${q}iI sum $n ${q}+i.toString)") - } - annotated.foreach{ m => - val n = m.takeWhile(_.isLetter) - val c = if (m contains "*") "ssI" else "spI" - pr( s" check(si, OnInt.sum(x.$n.$c(i)), ${q}$c sum $n ${q}+i.toString)") - } + parsefs(fs).foreach{ case (f, pf) => + pr(""" for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + } + if (sqnname(n)) { + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + } + if (parname(n)) { + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + } + } pr( s" }") + } + pr( s" } // End scope for operations $o collection $n") + } + } pr(""" wrong.foreach(println)""") pr(""" if (wrong.nonEmpty) sys.exit(1) """) pr(""" }""") diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index db8e4e4..689aa42 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -261,7 +261,7 @@ package object generate { class JlnThings(val sizes: Array[Int]) extends AbstractThings[java.util.LinkedList]("java.util.LinkedList") {} - class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151, 20000, 50000, 200000)) { + class Things(sizes: Array[Int] = Array(0, 1, 2, 5, 7, 15, 16, 32, 33, 64, 129, 256, 1023, 2914, 7151/*, 20000, 50000, 200000*/)) { def N = sizes.length lazy val arr = new ArrThings(sizes) lazy val ish = new IshThings(sizes) From 29b5ad11a5e061af5b669c9f897d36ef6d02224e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 13:31:28 -0800 Subject: [PATCH 079/340] All tests for agreement of results pass. That prerequisite for sane benchmarking is therefore met. --- benchmark/src/main/scala/bench/CodeGen.scala | 96 +++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 43623e3..fe46a2f 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -4,14 +4,24 @@ import scala.util._ import control.NonFatal object Generator { - val annotated = "arr ish lst* ils* que* stm* trs* vec arb ars ast* mhs lhs* prq* muq* wra jix jln".split(' ') - val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc")) - def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { case Array(x) => (x, None); case Array(x,y) => (x, Some(y)) }) + // Trailing * means that a collection is not expected to work efficiently in parallel + // Trailing ! means that a collection is not expected to maintain original order + val annotated = "arr ish! lst* ils*! que* stm* trs*! vec arb ars ast* mhs! lhs*! prq*! muq* wra jix jln".split(' ') + + // Parallel version if any appears after / + // Trailing ! means that collection must maintain original order (i.e. don't use if collection is marked !) + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc!"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc!")) + + def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { + case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!") + case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!") + }) val names = annotated.map(_.takeWhile(_.isLetter)) val nojname = names.filterNot(_ startsWith "j").toSet - val parname = annotated.filter(_.forall(_.isLetter)).toSet + val parname = annotated.filterNot(_ contains "*").map(_.takeWhile(_.isLetter)).toSet val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet + val ordname = annotated.filterNot(_ contains "!").map(_.takeWhile(_.isLetter)).toSet def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -30,53 +40,53 @@ object Generator { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - pr("""package bench.test""") - pr("""""") - pr("""import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") - pr("""import scala.compat.java8.StreamConverters._""") - pr("""""") - pr("""object Agreement {""") - pr(""" def run() {""") - pr(""" val wrong = new collection.mutable.ArrayBuffer[String]""") - pr(""" def check[A](a1: A, a2: => A, msg: String) {""") - pr(""" var t = System.nanoTime""") - pr(""" if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") - pr(""" wrong += msg""") - pr(""" if (t > 2000000000) wrong += "Slow " + msg""") - pr(""" }""") - pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") + pr( """ def check[A](a1: A, a2: => A, msg: String) {""") + pr( """ var t = System.nanoTime""") + pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr( """ wrong += msg""") + pr( """ if (t > 2000000000) wrong += "Slow " + msg""") + pr( """ }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf) => - pr(""" for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") - } - if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + parsefs(fs).foreach{ case (f, pf, ord) => + if (ordname(n) || !ord) { + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") + if (nojname(n)) { + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } - } - if (parname(n)) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") - if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + if (sqnname(n)) { + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + if (parname(n) && pf.isDefined) { + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } + pr( s" }") } - pr( s" }") } - pr( s" } // End scope for operations $o collection $n") + pr( s" } // End scope for operations $o collection $n") } } - pr(""" wrong.foreach(println)""") - pr(""" if (wrong.nonEmpty) sys.exit(1) """) - pr(""" }""") - pr("""}""") + pr( """ wrong.foreach(println)""") + pr( """ if (wrong.nonEmpty) sys.exit(1) """) + pr( """ }""") + pr( """}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => From 00977b83ef2a0837dc3e7417aa48ecff7448d673 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 14:15:50 -0800 Subject: [PATCH 080/340] Added overlooked Operations file! Also wrote a first pass of a Thyme benchmark generator. --- benchmark/src/main/scala/bench/CodeGen.scala | 129 +++++++++++++----- .../src/main/scala/bench/Operations.scala | 117 ++++++++++++++++ 2 files changed, 215 insertions(+), 31 deletions(-) create mode 100644 benchmark/src/main/scala/bench/Operations.scala diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index fe46a2f..c0e6e1b 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -40,53 +40,120 @@ object Generator { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => - pr( """package bench.test""") - pr( """""") - pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") - pr( """import scala.compat.java8.StreamConverters._""") - pr( """""") - pr( """object Agreement {""") - pr( """ def run() {""") - pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") - pr( """ def check[A](a1: A, a2: => A, msg: String) {""") - pr( """ var t = System.nanoTime""") - pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") - pr( """ wrong += msg""") - pr( """ if (t > 2000000000) wrong += "Slow " + msg""") - pr( """ }""") - pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val wrong = new collection.mutable.ArrayBuffer[String]""") + pr( """ def check[A](a1: A, a2: => A, msg: String) {""") + pr( """ var t = System.nanoTime""") + pr( """ if (!CloseEnough(a1, { val ans = a2; t = System.nanoTime - t; ans}))""") + pr( """ wrong += msg""") + pr( """ if (t > 2000000000) wrong += "Slow " + msg""") + pr( """ }""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { - pr( """ for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } - pr( s" }") + pr( s" }") } } - pr( s" } // End scope for operations $o collection $n") + pr( s" } // End scope for operations $o collection $n") } } - pr( """ wrong.foreach(println)""") - pr( """ if (wrong.nonEmpty) sys.exit(1) """) - pr( """ }""") - pr( """}""") + pr( """ wrong.foreach(println)""") + pr( """ if (wrong.nonEmpty) sys.exit(1) """) + pr( """ }""") + pr( """}""") + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } + + def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) { + val q = "\"" + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """import ichi.bench.Thyme""") + pr( """""") + pr( """object Agreement {""") + pr( """ def run() {""") + pr( """ val th = Thyme.warmed()""") + pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) + pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""") + pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""") + pr( """ for (i <- 0 until m) {""") + pr( """ val b = Thyme.Benched.empty""") + pr( """ val a = th.bench(op(i))(b)""") + pr( """ if (a == null) ts += ((Double.NaN, Double.NaN, Double.NaN))""") + pr( """ else ts += ((b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6)""") + pr( """ }""") + pr( """ val sb = new StringBuilder""") + pr( """ sb ++= name + $q: $q""") + pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""") + pr( """ ts.foreach{ case (c, lo, hi) =>""") + pr( """ sb ++= $q $q""") + pr( """ sb ++= ${q}12.4f${q}.format(c)""") + pr( """ sb ++= ${q}12.4f${q}.format(lo)""") + pr( """ sb ++= ${q}12.4f${q}.format(hi)""") + pr( """ }""") + pr( """ println(sb.result)""") + pr( """ }""") + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + pr( s" { // Scope for operations $o collection $n") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + parsefs(fs).foreach{ case (f, pf, ord) => + if (ordname(n) || !ord) { + if (nojname(n)) { + pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + } + if (sqnname(n)) { + pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + } + if (parname(n) && pf.isDefined) { + pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + if (nojname(n)) + pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + } + pr( s" }") + } + } + pr( s" } // End scope for operations $o collection $n") + } + } + pr( """ }""") + pr( """}""") } match { case Left(t) => println("Did not successfully write file: " + target.getPath); throw t case _ => diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala new file mode 100644 index 0000000..38c3f4c --- /dev/null +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -0,0 +1,117 @@ +package bench.operate + +import java.util.stream._ +import java.util.{function => jf} +import scala.compat.java8.StreamConverters._ +import scala.compat.java8.converterImpl._ +import scala.compat.java8.collectionImpl._ + +object CloseEnough { + import scala.math._ + def apply[A](a: A, b: => A): Boolean = a match { + case da: Double => b match { + case db: Double => (da.isNaN && db.isNaN) || abs(da - db) <= max(1, max(abs(da), abs(db)))*1e-6 + case x => a == x + } + case _ => a == b + } +} + +object OnInt { + def expensive(i: Int) = { var v = i.toDouble; var j = 0; while (j < 10) { v = math.exp(math.sin(v)); j += 1 }; v+j } + + def sum(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { s += a(i); i += 1 }; s } + def sum(t: Traversable[Int]): Int = t.sum + def sum(i: Iterator[Int]): Int = i.sum + def sum(s: IntStepper): Int = s.fold(0)(_ + _) + def sum(s: IntStream): Int = s.sum + def psum(i: Iterable[Int]): Int = i.par.sum + def psum(s: IntStream): Int = s.parallel.sum + + def trig(a: Array[Int]): Double = { var i = 0; var s = 0.0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } + def trig(t: Traversable[Int]): Double = t.map(expensive).sum + def trig(i: Iterator[Int]): Double = i.map(expensive).sum + def trig(s: IntStepper): Double = s.fold(0.0)((x,i) => x + expensive(i)) + def trig(s: IntStream): Double = s.mapToDouble(new jf.IntToDoubleFunction{ def applyAsDouble(i: Int) = expensive(i) }).sum + def ptrig(i: Iterable[Int]): Double = i.par.map(expensive).sum + def ptrig(s: IntStream): Double = trig(s.parallel) + + def fmc(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { if (i%7 == 1) s += (i/7)*i; i += 1 }; s } + def fmc(t: Traversable[Int]): Int = t.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def fmc(i: Iterator[Int]): Int = i.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def fmc(s: IntStream): Int = s. + filter(new jf.IntPredicate { def test(x: Int) = (x%7) == 1 }). + map(new jf.IntUnaryOperator{ def applyAsInt(x: Int) = (x/7)*x }). + sum + def pfmc(i: Iterable[Int]): Int = i.par.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def pfmc(s: IntStream): Int = fmc(s.parallel) + + def mdtc(a: Array[Int]): Int = { var i = 1; while(i < a.length) { if ((a(i) << 1) >= 42) return i-1; i += 1 }; i - 1 } + def mdtc(t: Traversable[Int]): Int = t.map(_ << 1).drop(1).takeWhile(_ < 42).size + def mdtc(i: Iterator[Int]): Int = i.map(_ << 1).drop(1).takeWhile(_ < 42).size + def mdtc(s: IntStream): Int = { + val temp = s.map(new jf.IntUnaryOperator { def applyAsInt(x: Int) = x << 1 }).skip(1) + val acc = new IntAccumulator + temp.allMatch(new jf.IntPredicate{ def test(x: Int) = if (x < 42) { acc += x; true } else false }) + acc.size.toInt + } +} + +object OnString { + def expensive(s: String) = { val h = scala.util.hashing.MurmurHash3.stringHash(s); OnInt.expensive(h) } + + def nbr(a: Array[String]): Int = { var s,i = 0; while (i < a.length) { if (a(i).charAt(a(i).length-1) < '5') s += 1; i += 1 }; s } + def nbr(t: Traversable[String]): Int = t.count(s => s.charAt(s.length-1) < '5') + def nbr(i: Iterator[String]): Int = i.count(s => s.charAt(s.length-1) < '5') + def nbr(p: Stepper[String]): Int = p.fold(0)((i,s) => if (s.charAt(s.length-1) < '5') i+1 else i) + def nbr(q: Stream[String]): Int = q.filter(new jf.Predicate[String] { def test(s: String) = s.charAt(s.length-1) < '5' }).count.toInt + def pnbr(i: Iterable[String]): Int = i.par.count(s => s.charAt(s.length-1) < '5') + def pnbr(q: Stream[String]): Int = nbr(q.parallel) + + def htrg(a: Array[String]): Double = { var s = 0.0; var i = 0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } + def htrg(t: Traversable[String]): Double = t.map(expensive).sum + def htrg(i: Iterator[String]): Double = i.map(expensive).sum + def htrg(p: Stepper[String]): Double = p.fold(0.0)((x,s) => x + expensive(s)) + def htrg(q: Stream[String]): Double = q.mapToDouble(new jf.ToDoubleFunction[String]{ def applyAsDouble(s: String) = expensive(s) }).sum + def phtrg(i: Iterable[String]): Double = i.par.map(expensive).sum + def phtrg(q: Stream[String]): Double = htrg(q.parallel) + + def fmc(a: Array[String]): Int = { + var s, i = 0 + while (i < a.length) { + val x = a(i) + if (x.charAt(x.length-1) == '1' && (x.length > 2 || (x.charAt(0) != '-' && x.length > 1))) s += 1 + i += 1 + } + s + } + def fmc(t: Traversable[String]): Int = + t.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def fmc(i: Iterator[String]): Int = + i.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def fmc(q: Stream[String]): Int = + q.filter(new jf.Predicate[String]{ def test(x: String) = x.charAt(x.length-1) == '1' }). + map[String](new jf.Function[String, String]{ def apply(x: String) = if (x.charAt(0) == '-') x.substring(1) else x }). + filter(new jf.Predicate[String]{ def test(x: String) = x.length > 1 }). + count.toInt + def pfmc(i: Iterable[String]): Int = + i.par.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def pfmc(q: Stream[String]): Int = fmc(q.parallel) + + def mdtc(a: Array[String]): Int = { + var i = 1 + while (i < a.length) { + if (a(i).reverse.length >= 3) return i-1 + i += 1 + } + i-1 + } + def mdtc(t: Traversable[String]): Int = t.map(_.reverse).drop(1).takeWhile(_.length < 3).size + def mdtc(i: Iterator[String]): Int = i.map(_.reverse).drop(1).takeWhile(_.length < 3).size + def mdtc(q: Stream[String]): Int = { + val temp = q.map[String](new jf.UnaryOperator[String] { def apply(x: String) = x.reverse }).skip(1) + val acc = new Accumulator[String] + temp.allMatch(new jf.Predicate[String]{ def test(x: String) = if (x.length < 3) { acc += x; true } else false }) + acc.size.toInt + } +} From 8ab04680a29f6fa25a2dcdc4305c078917fe4982 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 2 Jan 2016 18:13:49 -0800 Subject: [PATCH 081/340] JMH benchmarks working, and take less time than forever. --- benchmark/src/main/scala/bench/CodeGen.scala | 111 ++++++++++++++----- 1 file changed, 82 insertions(+), 29 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index c0e6e1b..7563a88 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -22,6 +22,7 @@ object Generator { val parname = annotated.filterNot(_ contains "*").map(_.takeWhile(_.isLetter)).toSet val sqnname = names.filterNot(parname).toSet union names.filterNot(nojname).toSet val ordname = annotated.filterNot(_ contains "!").map(_.takeWhile(_.isLetter)).toSet + val jmhsizes = Array(10, 10000) // JMH takes FOREVER, so we're lucky to get two sizes. def writeTo(f: java.io.File)(pr: (String => Unit) => Unit): Either[Throwable, Unit] = { try { @@ -57,29 +58,30 @@ object Generator { pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { - pr( """ for (i <- 0 until m) {""") - pr( s" val z = $o.$f(x.arr.c$t(i))") + pr( """ for (i <- 0 until m) {""") + pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") } if (sqnname(n)) { - pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") } - pr( s" }") + pr( s" }") } } + pr( s" x = null // Allow GC" ) pr( s" } // End scope for operations $o collection $n") } } @@ -93,7 +95,7 @@ object Generator { } } - def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]]) { + def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]] = None) { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => @@ -103,52 +105,56 @@ object Generator { pr( """import scala.compat.java8.StreamConverters._""") pr( """import ichi.bench.Thyme""") pr( """""") - pr( """object Agreement {""") + pr( """object ThymeBench {""") pr( """ def run() {""") pr( """ val th = Thyme.warmed()""") pr( s" val m = (new bench.generate.Things(${sayArrayI(sizes)})).N;" ) pr( """ def timings[A](x: bench.generate.Things, op: Int => A, name: String) {""") pr( """ val ts = new collection.mutable.ArrayBuffer[(Double, Double, Double)]""") + pr( """ val discard = th.clock(op(m-1))(_ => ()) // Init collections""") pr( """ for (i <- 0 until m) {""") + pr( """ println(name + i)""") pr( """ val b = Thyme.Benched.empty""") pr( """ val a = th.bench(op(i))(b)""") pr( """ if (a == null) ts += ((Double.NaN, Double.NaN, Double.NaN))""") - pr( """ else ts += ((b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6)""") + pr( """ else ts += ((""") + pr( """ b.runtime * 1e6, b.runtimeCI95._1 * 1e6, b.runtimeCI95._2 * 1e6""") + pr( """ ))""") pr( """ }""") pr( """ val sb = new StringBuilder""") - pr( """ sb ++= name + $q: $q""") - pr( """ if (sb.length < 36) sb ++= $q $q * (36 - sb.length)""") + pr( """ sb ++= name + ":" """) + pr( """ if (sb.length < 16) sb ++= " " * (16 - sb.length)""") pr( """ ts.foreach{ case (c, lo, hi) =>""") - pr( """ sb ++= $q $q""") - pr( """ sb ++= ${q}12.4f${q}.format(c)""") - pr( """ sb ++= ${q}12.4f${q}.format(lo)""") - pr( """ sb ++= ${q}12.4f${q}.format(hi)""") + pr( """ sb ++= " " """) + pr( """ sb ++= " %11.4f".format(c)""") + pr( """ sb ++= " %11.4f".format(lo)""") + pr( """ sb ++= " %11.4f".format(hi)""") pr( """ }""") pr( """ println(sb.result)""") pr( """ }""") allops.foreach{ case (o, t, fs) => names.foreach{ n => - pr( s" { // Scope for operations $o collection $n") - pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})" ) + pr( s" { // Scope for operations $o collection $n") + pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) parsefs(fs).foreach{ case (f, pf, ord) => if (ordname(n) || !ord) { if (nojname(n)) { - pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); - pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n${q})"); + pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n${q})") } if (sqnname(n)) { - pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n${q})") if (nojname(n)) - pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n${q})") } if (parname(n) && pf.isDefined) { - pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n${q})") if (nojname(n)) - pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" timings(x, i => $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n${q})") } - pr( s" }") } } + pr( s" x = null // Allow GC" ) pr( s" } // End scope for operations $o collection $n") } } @@ -159,4 +165,51 @@ object Generator { case _ => } } + + def jmhBench(target: java.io.File = new java.io.File("JmhBench.scala"), sizes: Option[Array[Int]] = Some(jmhsizes)) { + val q = "\"" + if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) + writeTo(target){ pr => + pr( """// This file auto-generated by bench.codegen.Generator.jmhBench. Do not modify directly.""") + pr( """""") + pr( """package bench.test""") + pr( """""") + pr( """import bench.generate._, bench.operate._, bench.generate.EnableIterators._""") + pr( """import scala.compat.java8.StreamConverters._""") + pr( """import org.openjdk.jmh.annotations._""") + pr( """""") + pr( """@State(Scope.Benchmark)""") + pr( """class JmhBench {""") + pr( s" val x = new bench.generate.Things(${sayArrayI(sizes)})") + val m = sizes.map(_.length).getOrElse(new bench.generate.Things().N) + allops.foreach{ case (o, t, fs) => + names.foreach{ n => + parsefs(fs).foreach{ case (f, pf, ord) => + for (i <- 0 until m) { + if (ordname(n) || !ord) { + if (nojname(n)) { + pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))"); + pr( s" @Benchmark def bench_i${t}_${f}_${n}_$i() = $o.$f(x.$n.i$t($i))") + } + if (sqnname(n)) { + pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") + } + if (parname(n) && pf.isDefined) { + pr( s" @Benchmark def bench_sp${t}_${f}_${n}_$i() = $o.$f(x.$n.sp$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zp${t}_${f}_${n}_$i() = $o.$f(x.$n.zp$t($i))") + } + } + } + } + } + } + pr( """}""") + } match { + case Left(t) => println("Did not successfully write file: " + target.getPath); throw t + case _ => + } + } } From bea1d3936cccdf3c145c7ce565ae018f1381526e Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 8 Jan 2016 12:36:39 -0800 Subject: [PATCH 082/340] Added docs and benchmark results. --- README.md | 56 + benchmark/README.md | 33 + benchmark/project/plugins.sbt | 2 +- benchmark/results/jmhbench.graphs.ascii | 2537 +++++++++++++++++ benchmark/results/jmhbench.log | 1054 +++++++ benchmark/src/main/scala/bench/CodeGen.scala | 59 +- .../src/main/scala/bench/Operations.scala | 29 +- .../src/main/scala/bench/ParseJmhLog.scala | 146 + .../java8/converterImpl/MakesSteppers.scala | 2 +- 9 files changed, 3883 insertions(+), 35 deletions(-) create mode 100644 benchmark/README.md create mode 100644 benchmark/results/jmhbench.graphs.ascii create mode 100644 benchmark/results/jmhbench.log create mode 100644 benchmark/src/main/scala/bench/ParseJmhLog.scala diff --git a/README.md b/README.md index b757697..6f7b472 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,31 @@ are used for collections, so this is best done to gather the results of an expen Finally, there is a Java class, `ScalaStreamer`, that has a series of `from` methods that can be used to obtain Java 8 Streams from Scala collections from within Java. +#### Performance Considerations + +For sequential operations, Scala's `iterator` almost always equals or exceeds the performance of a Java 8 stream. Thus, +one should favor `iterator` (and its richer set of operations) over `seqStream` for general use. However, long +chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, +`IntStream`, and `LongStream`. + +Note that although `iterator` typically has superior performance in a sequential context, the advantage is modest +(usually less than 50% higher throughput for `iterator`). + +For parallel operations, `parStream` and even `seqStream.parallel` meets or exceeds the performance of Scala parallel +collections methods (invoked with `.par`). Especially for small collections, the difference can be substantial. In +some cases, when a Scala (parallel) collection is the ultimate result, Scala parallel collections can have an advantage +as the collection can (in some cases) be built in parallel. + +Because the wrappers are invoked based on the static type of the collection, there are also cases where parallelization +is inefficient when interfacing with Java 8 Streams (e.g. when a collection is typed as `Seq[String]` so might have linear +access like `List`, but actually is a `WrappedArray[String]` that can be efficiently parallelized) but can be efficient +with Scala parallel collections. The `parStream` method is only available when the static type is known to be compatible +with rapid parallel operation; `seqStream` can be parallelized by using `.parallel`, but may or may not be efficient. + +If the operations available on Java 8 Streams are sufficient, the collection type is known statically with enough precision +to enable parStream, and an `Accumulator` or non-collection type is an acceptable result, Java 8 Streams will essentially +always outperform the Scala parallel collections. + #### Scala Usage Example ```scala @@ -158,6 +183,37 @@ object Test { } ``` +#### Using Java 8 Streams with Scala Function Converters + +Scala can emit Java SAMs for lambda expressions that are arguments to methods that take a Java SAM rather than +a Scala Function. However, it can be convenient to restrict the SAM interface to interactions with Java code +(including Java 8 Streams) rather than having it propagate throughout Scala code. + +Using Java 8 Stream converters together with function converters allows one to accomplish this with only a modest +amount of fuss. + +Example: + +```scala +import scala.compat.java8.FunctionConverters._ +import scala.compat.java8.StreamConverters._ + +def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = + xs.parStream. // Creates java.util.stream.Stream[String] + map[String](f.asJava).sorted. // Maps A to String and sorts (in parallel) + toArray.mkString(sep) // Back to an Array to use Scala's mkString +``` + +Note that explicit creation of a new lambda will tend to lead to improved type inference and at least equal +performance: + +```scala +def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = + xs.parStream. + map[String](a => f(a)).sorted. // Explicit lambda creates a SAM wrapper for f + toArray.mkString(sep) +``` + #### Java Usage Example ```java diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 0000000..eb68ef9 --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,33 @@ +# Benchmark suite for Java 8 Streams compatibility layer + +This project is intended to support semi-manual benchmarking of the Java 8 streams compatibility layer in Scala collections. + +Because the benchmarking is **very computationally expensive** it should be done occasionally, not automatically. + +## Code generation step + +1. Run `sbt console` + +2. If the `JmhBench.scala` file already exists, delete it. + +3. Enter `bench.codegen.Generate.jmhBench()` to generate the `JmhBench.scala` file. + +## Benchmarking step + +1. Make sure your terminal has plenty of lines of scrollback. (A couple thousand should do.) + +2. Run `sbt` + +3. Enter `jmh:run -i 5 -wi 3 -f5`. Wait overnight. + +4. Clip off the last set of lines from the terminal window starting before the line that contains `[info] # Run complete. Total time:` and including that line until the end. + +5. Save that in the file `results/jmhbench.log` + +## Comparison step + +1. Run `sbt console` + +2. Enter `bench.examine.SpeedReports()` + +3. Look at the ASCII art results showing speed comparisons. diff --git a/benchmark/project/plugins.sbt b/benchmark/project/plugins.sbt index d85fed8..c5220d0 100644 --- a/benchmark/project/plugins.sbt +++ b/benchmark/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.4") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.5") diff --git a/benchmark/results/jmhbench.graphs.ascii b/benchmark/results/jmhbench.graphs.ascii new file mode 100644 index 0000000..b6f4c9d --- /dev/null +++ b/benchmark/results/jmhbench.graphs.ascii @@ -0,0 +1,2537 @@ +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + Int, base collection ##= 0.112 +- 9.4 % + Int, iterator on coll #### 0.160 +- 14.7 % + Int, serial stream ###- 0.129 +- 9.6 % + +filter/map/sum trio +10 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ###= 0.150 +- 10.1 % + Int, serial stream #####= 0.223 +- 6.0 % + +filter/map/sum trio +10 elements +collection.mutable.ArraySeq + Int, base collection #= 0.068 +- 12.4 % + Int, iterator on coll ##### 0.197 +- 11.1 % + Int, serial stream ### 0.122 +- 8.4 % + +filter/map/sum trio +10 elements +collection.mutable.ArrayStack + Int, base collection ## 0.081 +- 5.1 % + Int, iterator on coll ####- 0.171 +- 1.4 % + Int, serial stream ##= 0.113 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.ListSet + Int, base collection # 0.037 +- 15.6 % + Int, iterator on coll ####= 0.185 +- 15.0 % + Int, serial stream ##- 0.091 +- 6.1 % + +filter/map/sum trio +10 elements +collection.immutable.HashSet + Int, base collection #= 0.069 +- 13.0 % + Int, iterator on coll ###- 0.132 +- 14.3 % + Int, serial stream ##= 0.111 +- 10.1 % + +filter/map/sum trio +10 elements +java.util.ArrayList + Int, serial stream ###= 0.144 +- 7.1 % + +filter/map/sum trio +10 elements +java.util.LinkedList + Int, serial stream ###= 0.141 +- 3.2 % + +filter/map/sum trio +10 elements +collection.mutable.LinkedHashSet + Int, base collection ## 0.081 +- 17.3 % + Int, iterator on coll ####= 0.189 +- 0.6 % + Int, serial stream ### 0.114 +- 0.8 % + +filter/map/sum trio +10 elements +collection.immutable.List + Int, base collection ##- 0.099 +- 6.1 % + Int, iterator on coll #### 0.165 +- 20.9 % + Int, serial stream ##= 0.104 +- 11.6 % + +filter/map/sum trio +10 elements +collection.mutable.HashSet + Int, base collection #- 0.060 +- 1.1 % + Int, iterator on coll ##= 0.106 +- 1.2 % + Int, serial stream ##= 0.101 +- 6.6 % + +filter/map/sum trio +10 elements +collection.mutable.Queue + Int, base collection # 0.035 +- 13.4 % + Int, iterator on coll ##= 0.106 +- 0.8 % + Int, serial stream # 0.046 +- 7.3 % + +filter/map/sum trio +10 elements +collection.mutable.PriorityQueue + Int, base collection ##- 0.092 +- 3.6 % + Int, iterator on coll ####- 0.174 +- 12.0 % + Int, serial stream ### 0.118 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.Queue + Int, base collection #= 0.069 +- 1.7 % + Int, iterator on coll ### 0.124 +- 21.0 % + Int, serial stream ##= 0.102 +- 3.2 % + +filter/map/sum trio +10 elements +collection.immutable.Stream + Int, base collection ## 0.075 +- 5.5 % + Int, iterator on coll #- 0.056 +- 4.7 % + Int, serial stream ##= 0.102 +- 15.3 % + +filter/map/sum trio +10 elements +collection.immutable.TreeSet + Int, base collection #= 0.069 +- 3.9 % + Int, iterator on coll ### 0.125 +- 3.5 % + Int, serial stream ##= 0.108 +- 1.4 % + +filter/map/sum trio +10 elements +collection.immutable.Vector + Int, base collection ##- 0.093 +- 2.9 % + Int, iterator on coll #### 0.164 +- 1.2 % + Int, serial stream ###- 0.127 +- 2.7 % + +filter/map/sum trio +10 elements +collection.mutable.WrappedArray + Int, base collection ##- 0.095 +- 2.1 % + Int, iterator on coll ###- 0.128 +- 0.6 % + Int, serial stream ###- 0.129 +- 4.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + Int, base collection #####= 0.225 +- 0.7 % + Int, iterator on coll ######- 0.258 +- 0.4 % + Int, serial stream ##= 0.101 +- 7.9 % + +filter/map/sum trio +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll #### 0.165 +- 2.9 % + Int, serial stream ####################= 0.833 +- 1.8 % + +filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + Int, base collection ####= 0.181 +- 3.2 % + Int, iterator on coll ######- 0.258 +- 0.7 % + Int, serial stream ##- 0.098 +- 8.6 % + +filter/map/sum trio +10000 elements +collection.mutable.ArrayStack + Int, base collection ####= 0.187 +- 1.3 % + Int, iterator on coll ######= 0.273 +- 0.5 % + Int, serial stream ##= 0.109 +- 5.0 % + +filter/map/sum trio +10000 elements +collection.immutable.ListSet + Int, base collection 0.005 +- 5.2 % + Int, iterator on coll #####- 0.214 +- 1.3 % + Int, serial stream ##- 0.099 +- 3.6 % + +filter/map/sum trio +10000 elements +collection.immutable.HashSet + Int, base collection # 0.037 +- 9.0 % + Int, iterator on coll ##= 0.107 +- 0.6 % + Int, serial stream ##- 0.092 +- 0.9 % + +filter/map/sum trio +10000 elements +java.util.ArrayList + Int, serial stream ######- 0.256 +- 5.5 % + +filter/map/sum trio +10000 elements +java.util.LinkedList + Int, serial stream ####### 0.280 +- 3.4 % + +filter/map/sum trio +10000 elements +collection.mutable.LinkedHashSet + Int, base collection ## 0.082 +- 4.3 % + Int, iterator on coll ######= 0.261 +- 2.9 % + Int, serial stream ##= 0.112 +- 6.3 % + +filter/map/sum trio +10000 elements +collection.immutable.List + Int, base collection ###- 0.135 +- 1.8 % + Int, iterator on coll #####- 0.215 +- 1.6 % + Int, serial stream #= 0.060 +- 1.6 % + +filter/map/sum trio +10000 elements +collection.mutable.HashSet + Int, base collection # 0.046 +- 2.7 % + Int, iterator on coll ##= 0.111 +- 1.6 % + Int, serial stream ##= 0.109 +- 2.1 % + +filter/map/sum trio +10000 elements +collection.mutable.Queue + Int, base collection #- 0.059 +- 1.1 % + Int, iterator on coll ##### 0.204 +- 1.2 % + Int, serial stream #- 0.051 +- 2.4 % + +filter/map/sum trio +10000 elements +collection.mutable.PriorityQueue + Int, base collection ##= 0.103 +- 9.3 % + Int, iterator on coll ######- 0.248 +- 0.6 % + Int, serial stream ##- 0.088 +- 4.4 % + +filter/map/sum trio +10000 elements +collection.immutable.Queue + Int, base collection ## 0.079 +- 0.7 % + Int, iterator on coll #####- 0.211 +- 2.5 % + Int, serial stream ##= 0.113 +- 1.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Stream + Int, base collection ##- 0.087 +- 2.4 % + Int, iterator on coll #- 0.050 +- 6.6 % + Int, serial stream ##- 0.089 +- 31.9 % + +filter/map/sum trio +10000 elements +collection.immutable.TreeSet + Int, base collection = 0.023 +- 2.5 % + Int, iterator on coll ###= 0.146 +- 1.6 % + Int, serial stream ## 0.083 +- 2.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Vector + Int, base collection #### 0.159 +- 5.3 % + Int, iterator on coll ##### 0.206 +- 0.9 % + Int, serial stream ##= 0.104 +- 18.7 % + +filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + Int, base collection ### 0.125 +- 1.9 % + Int, iterator on coll #### 0.157 +- 3.4 % + Int, serial stream ##- 0.091 +- 8.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + String, base collection #### 0.153 +- 0.6 % + String, iterator on coll #########= 0.381 +- 1.0 % + String, serial stream ###- 0.138 +- 10.2 % + +filter/map/sum trio +10 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll #########= 0.389 +- 1.0 % + String, serial stream ###= 0.142 +- 8.6 % + +filter/map/sum trio +10 elements +collection.mutable.ArraySeq + String, base collection ##- 0.094 +- 4.2 % + String, iterator on coll #########= 0.382 +- 0.4 % + String, serial stream ###- 0.136 +- 10.0 % + +filter/map/sum trio +10 elements +collection.mutable.ArrayStack + String, base collection ### 0.124 +- 1.3 % + String, iterator on coll ###########= 0.473 +- 1.2 % + String, serial stream ### 0.125 +- 10.5 % + +filter/map/sum trio +10 elements +collection.immutable.ListSet + String, base collection #- 0.054 +- 4.9 % + String, iterator on coll ######= 0.265 +- 1.2 % + String, serial stream ##= 0.102 +- 3.1 % + +filter/map/sum trio +10 elements +collection.immutable.HashSet + String, base collection ##- 0.093 +- 3.1 % + String, iterator on coll ##### 0.205 +- 2.7 % + String, serial stream ##- 0.097 +- 2.9 % + +filter/map/sum trio +10 elements +java.util.ArrayList + String, serial stream #### 0.159 +- 6.3 % + +filter/map/sum trio +10 elements +java.util.LinkedList + String, serial stream ###= 0.150 +- 4.1 % + +filter/map/sum trio +10 elements +collection.mutable.LinkedHashSet + String, base collection ###- 0.134 +- 1.4 % + String, iterator on coll ##########- 0.419 +- 0.7 % + String, serial stream ### 0.125 +- 10.9 % + +filter/map/sum trio +10 elements +collection.immutable.List + String, base collection ###- 0.138 +- 3.0 % + String, iterator on coll ########## 0.401 +- 1.1 % + String, serial stream ##= 0.105 +- 17.2 % + +filter/map/sum trio +10 elements +collection.mutable.HashSet + String, base collection ##= 0.102 +- 2.1 % + String, iterator on coll ######- 0.252 +- 0.6 % + String, serial stream ##- 0.091 +- 20.6 % + +filter/map/sum trio +10 elements +collection.mutable.Queue + String, base collection # 0.035 +- 1.9 % + String, iterator on coll ####- 0.178 +- 1.6 % + String, serial stream #- 0.058 +- 5.1 % + +filter/map/sum trio +10 elements +collection.mutable.PriorityQueue + String, base collection ### 0.117 +- 1.0 % + String, iterator on coll ########## 0.398 +- 2.4 % + String, serial stream ### 0.120 +- 10.1 % + +filter/map/sum trio +10 elements +collection.immutable.Queue + String, base collection ##= 0.102 +- 4.6 % + String, iterator on coll ######### 0.357 +- 1.5 % + String, serial stream ##- 0.097 +- 11.5 % + +filter/map/sum trio +10 elements +collection.immutable.Stream + String, base collection ##= 0.101 +- 7.1 % + String, iterator on coll #= 0.073 +- 5.8 % + String, serial stream ##= 0.110 +- 12.1 % + +filter/map/sum trio +10 elements +collection.immutable.TreeSet + String, base collection ##- 0.097 +- 1.6 % + String, iterator on coll ##### 0.194 +- 5.2 % + String, serial stream ##= 0.102 +- 7.8 % + +filter/map/sum trio +10 elements +collection.immutable.Vector + String, base collection ### 0.126 +- 0.8 % + String, iterator on coll #######- 0.299 +- 7.3 % + String, serial stream ### 0.123 +- 12.2 % + +filter/map/sum trio +10 elements +collection.mutable.WrappedArray + String, base collection ### 0.123 +- 1.1 % + String, iterator on coll ##########- 0.409 +- 0.4 % + String, serial stream ###- 0.135 +- 9.9 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########- 0.328 +- 1.2 % + String, iterator on coll ############# 0.518 +- 0.6 % + String, serial stream ##########= 0.427 +- 1.0 % + +filter/map/sum trio +10000 elements +Array + String, base collection ######################### 1.000 +- 0.8 % + String, iterator on coll #############= 0.548 +- 0.9 % + String, serial stream ########### 0.442 +- 13.1 % + +filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + String, base collection #######- 0.292 +- 5.3 % + String, iterator on coll ############# 0.523 +- 0.6 % + String, serial stream ########= 0.342 +- 17.6 % + +filter/map/sum trio +10000 elements +collection.mutable.ArrayStack + String, base collection ######## 0.325 +- 1.8 % + String, iterator on coll ############### 0.600 +- 0.8 % + String, serial stream ########- 0.338 +- 15.3 % + +filter/map/sum trio +10000 elements +collection.immutable.ListSet + String, base collection 0.003 +- 8.8 % + String, iterator on coll ############# 0.516 +- 1.7 % + String, serial stream #######= 0.306 +- 12.0 % + +filter/map/sum trio +10000 elements +collection.immutable.HashSet + String, base collection #- 0.054 +- 1.3 % + String, iterator on coll ### 0.118 +- 0.8 % + String, serial stream ##= 0.103 +- 0.5 % + +filter/map/sum trio +10000 elements +java.util.ArrayList + String, serial stream ############ 0.478 +- 8.2 % + +filter/map/sum trio +10000 elements +java.util.LinkedList + String, serial stream ############- 0.496 +- 8.7 % + +filter/map/sum trio +10000 elements +collection.mutable.LinkedHashSet + String, base collection ##- 0.091 +- 0.5 % + String, iterator on coll #############= 0.545 +- 1.1 % + String, serial stream #########= 0.392 +- 10.3 % + +filter/map/sum trio +10000 elements +collection.immutable.List + String, base collection ####- 0.175 +- 3.4 % + String, iterator on coll ############= 0.511 +- 2.1 % + String, serial stream #######= 0.301 +- 0.7 % + +filter/map/sum trio +10000 elements +collection.mutable.HashSet + String, base collection #- 0.047 +- 0.6 % + String, iterator on coll ##= 0.108 +- 0.5 % + String, serial stream ### 0.117 +- 0.3 % + +filter/map/sum trio +10000 elements +collection.mutable.Queue + String, base collection # 0.046 +- 0.7 % + String, iterator on coll ###########= 0.461 +- 1.3 % + String, serial stream ##- 0.097 +- 1.7 % + +filter/map/sum trio +10000 elements +collection.mutable.PriorityQueue + String, base collection ### 0.115 +- 10.9 % + String, iterator on coll #########- 0.376 +- 2.2 % + String, serial stream ###### 0.245 +- 1.0 % + +filter/map/sum trio +10000 elements +collection.immutable.Queue + String, base collection ###- 0.135 +- 2.0 % + String, iterator on coll ############# 0.516 +- 0.9 % + String, serial stream #####= 0.220 +- 2.2 % + +filter/map/sum trio +10000 elements +collection.immutable.Stream + String, base collection ### 0.120 +- 2.5 % + String, iterator on coll ## 0.086 +- 6.3 % + String, serial stream ###### 0.235 +- 5.3 % + +filter/map/sum trio +10000 elements +collection.immutable.TreeSet + String, base collection = 0.024 +- 0.9 % + String, iterator on coll ###= 0.146 +- 3.4 % + String, serial stream ###= 0.148 +- 0.6 % + +filter/map/sum trio +10000 elements +collection.immutable.Vector + String, base collection #####- 0.207 +- 2.9 % + String, iterator on coll #########= 0.382 +- 1.8 % + String, serial stream ######### 0.353 +- 24.5 % + +filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + String, base collection ########- 0.334 +- 2.4 % + String, iterator on coll #############= 0.542 +- 0.9 % + String, serial stream #########- 0.376 +- 18.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trig on hashCode +10 elements +collection.mutable.ArrayBuffer + String, base collection ########################= 0.982 +- 0.1 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.3 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll ########################= 0.991 +- 0.2 % + String, serial stream ########################= 0.990 +- 0.3 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.ArraySeq + String, base collection #################= 0.704 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.3 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.ArrayStack + String, base collection #################= 0.701 +- 0.2 % + String, iterator on coll ########################= 0.988 +- 0.3 % + String, serial stream ########################= 0.988 +- 0.2 % + String Stepper (seq only) ######################### 0.994 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.ListSet + String, base collection #######################- 0.935 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.985 +- 0.9 % + String Stepper (seq only) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.HashSet + String, base collection #################- 0.689 +- 0.2 % + String, iterator on coll ########################= 0.989 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (can par) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +java.util.ArrayList + String, serial stream ######################### 0.995 +- 0.3 % + +slow trig on hashCode +10 elements +java.util.LinkedList + String, serial stream ######################### 0.997 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.LinkedHashSet + String, base collection ######################## 0.960 +- 0.4 % + String, iterator on coll ########################= 0.987 +- 0.3 % + String, serial stream ########################= 0.992 +- 0.2 % + String Stepper (seq only) ########################= 0.993 +- 0.4 % + +slow trig on hashCode +10 elements +collection.immutable.List + String, base collection ########################= 0.985 +- 0.2 % + String, iterator on coll ######################### 0.993 +- 0.2 % + String, serial stream ########################= 0.993 +- 0.2 % + String Stepper (seq only) ######################### 0.994 +- 0.3 % + +slow trig on hashCode +10 elements +collection.mutable.HashSet + String, base collection ######################## 0.960 +- 0.3 % + String, iterator on coll ########################= 0.984 +- 0.2 % + String, serial stream ########################= 0.989 +- 0.2 % + String Stepper (can par) ########################= 0.992 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.Queue + String, base collection #######################- 0.927 +- 0.4 % + String, iterator on coll ######################### 0.994 +- 0.3 % + String, serial stream ########################- 0.972 +- 0.3 % + String Stepper (seq only) ########################- 0.973 +- 0.2 % + +slow trig on hashCode +10 elements +collection.mutable.PriorityQueue + String, base collection ########################= 0.983 +- 0.2 % + String, iterator on coll ######################### 0.993 +- 0.3 % + String, serial stream ########################= 0.989 +- 0.4 % + String Stepper (seq only) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.Queue + String, base collection ######################## 0.966 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.986 +- 0.5 % + String Stepper (seq only) ######################### 0.993 +- 0.2 % + +slow trig on hashCode +10 elements +collection.immutable.Stream + String, base collection ######################## 0.956 +- 0.2 % + String, iterator on coll ########################- 0.975 +- 0.2 % + String, serial stream ########################= 0.987 +- 0.5 % + String Stepper (seq only) ######################### 0.994 +- 0.6 % + +slow trig on hashCode +10 elements +collection.immutable.TreeSet + String, base collection ################# 0.682 +- 0.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (seq only) ########################= 0.993 +- 0.3 % + +slow trig on hashCode +10 elements +collection.immutable.Vector + String, base collection ########################= 0.982 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ########################= 0.988 +- 0.3 % + String Stepper (can par) ########################= 0.991 +- 0.5 % + +slow trig on hashCode +10 elements +collection.mutable.WrappedArray + String, base collection ########################= 0.983 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ########################= 0.988 +- 0.4 % + String Stepper (can par) ######################### 0.995 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trig on hashCode +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########################= 0.989 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.2 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +Array + String, base collection ######################### 1.000 +- 0.1 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.996 +- 0.1 % + String Stepper (can par) ######################### 0.996 +- 0.3 % + +slow trig on hashCode +10000 elements +collection.mutable.ArraySeq + String, base collection ##################### 0.839 +- 11.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.994 +- 0.2 % + String Stepper (can par) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.ArrayStack + String, base collection #################= 0.713 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.994 +- 0.2 % + String Stepper (seq only) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.immutable.ListSet + String, base collection ######################= 0.913 +- 0.3 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ########################= 0.991 +- 0.2 % + String Stepper (seq only) ########################= 0.986 +- 1.0 % + +slow trig on hashCode +10000 elements +collection.immutable.HashSet + String, base collection ###############= 0.627 +- 0.4 % + String, iterator on coll ########################= 0.982 +- 0.2 % + String, serial stream ########################- 0.970 +- 0.1 % + String Stepper (can par) ########################= 0.981 +- 0.5 % + +slow trig on hashCode +10000 elements +java.util.ArrayList + String, serial stream ######################### 0.996 +- 0.1 % + +slow trig on hashCode +10000 elements +java.util.LinkedList + String, serial stream ######################### 0.996 +- 0.1 % + +slow trig on hashCode +10000 elements +collection.mutable.LinkedHashSet + String, base collection #######################= 0.941 +- 0.2 % + String, iterator on coll ########################= 0.993 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (seq only) ######################### 0.994 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.List + String, base collection ########################= 0.987 +- 0.2 % + String, iterator on coll ######################### 0.994 +- 0.2 % + String, serial stream ######################### 0.996 +- 0.1 % + String Stepper (seq only) ######################### 0.996 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.HashSet + String, base collection ####################### 0.916 +- 0.4 % + String, iterator on coll ########################- 0.977 +- 0.4 % + String, serial stream ########################- 0.979 +- 0.1 % + String Stepper (can par) ########################= 0.983 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.mutable.Queue + String, base collection ######################## 0.957 +- 0.3 % + String, iterator on coll ########################= 0.992 +- 0.3 % + String, serial stream ########################- 0.977 +- 0.2 % + String Stepper (seq only) ########################- 0.971 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.PriorityQueue + String, base collection #################= 0.711 +- 0.3 % + String, iterator on coll ########################= 0.988 +- 0.4 % + String, serial stream ########################= 0.989 +- 0.1 % + String Stepper (seq only) ########################= 0.990 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.Queue + String, base collection ########################- 0.972 +- 0.3 % + String, iterator on coll ########################= 0.993 +- 0.3 % + String, serial stream ########################= 0.987 +- 0.7 % + String Stepper (seq only) ########################= 0.990 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.immutable.Stream + String, base collection ######################## 0.954 +- 0.2 % + String, iterator on coll ########################- 0.975 +- 0.3 % + String, serial stream ########################= 0.992 +- 0.1 % + String Stepper (seq only) ########################= 0.993 +- 0.3 % + +slow trig on hashCode +10000 elements +collection.immutable.TreeSet + String, base collection ################ 0.635 +- 0.4 % + String, iterator on coll ########################= 0.983 +- 0.3 % + String, serial stream ########################= 0.981 +- 0.2 % + String Stepper (seq only) ########################= 0.983 +- 0.4 % + +slow trig on hashCode +10000 elements +collection.immutable.Vector + String, base collection ########################= 0.984 +- 0.2 % + String, iterator on coll ########################= 0.991 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trig on hashCode +10000 elements +collection.mutable.WrappedArray + String, base collection ########################= 0.986 +- 0.2 % + String, iterator on coll ########################= 0.992 +- 0.2 % + String, serial stream ######################### 0.995 +- 0.1 % + String Stepper (can par) ######################### 0.996 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10 elements +collection.mutable.ArrayBuffer + Int, base collection # 0.043 +- 0.7 % + Int, iterator on coll ###### 0.237 +- 14.9 % + Int, serial stream #= 0.067 +- 3.1 % + +map/filter/take trio +10 elements +Array + Int, base collection ######################### 1.000 +- 0.9 % + Int, iterator on coll ######- 0.257 +- 25.2 % + Int, serial stream ## 0.076 +- 2.2 % + +map/filter/take trio +10 elements +collection.mutable.ArraySeq + Int, base collection = 0.031 +- 1.2 % + Int, iterator on coll #####- 0.213 +- 20.9 % + Int, serial stream #= 0.065 +- 7.1 % + +map/filter/take trio +10 elements +collection.mutable.ArrayStack + Int, base collection = 0.023 +- 1.6 % + Int, iterator on coll ######- 0.259 +- 15.7 % + Int, serial stream #= 0.066 +- 1.0 % + +map/filter/take trio +10 elements +java.util.ArrayList + Int, serial stream #- 0.051 +- 1.8 % + +map/filter/take trio +10 elements +java.util.LinkedList + Int, serial stream #- 0.052 +- 4.6 % + +map/filter/take trio +10 elements +collection.immutable.List + Int, base collection #= 0.063 +- 2.1 % + Int, iterator on coll ######= 0.267 +- 2.3 % + Int, serial stream #- 0.059 +- 1.9 % + +map/filter/take trio +10 elements +collection.mutable.Queue + Int, base collection - 0.013 +- 4.4 % + Int, iterator on coll ###- 0.130 +- 3.8 % + Int, serial stream = 0.027 +- 2.4 % + +map/filter/take trio +10 elements +collection.immutable.Queue + Int, base collection = 0.022 +- 0.8 % + Int, iterator on coll #####= 0.222 +- 13.2 % + Int, serial stream #- 0.050 +- 2.0 % + +map/filter/take trio +10 elements +collection.immutable.Stream + Int, base collection - 0.013 +- 3.4 % + Int, iterator on coll # 0.039 +- 5.1 % + Int, serial stream #- 0.058 +- 2.7 % + +map/filter/take trio +10 elements +collection.immutable.Vector + Int, base collection #- 0.058 +- 1.1 % + Int, iterator on coll ######- 0.254 +- 2.1 % + Int, serial stream #= 0.066 +- 2.4 % + +map/filter/take trio +10 elements +collection.mutable.WrappedArray + Int, base collection # 0.045 +- 0.6 % + Int, iterator on coll #####- 0.209 +- 14.9 % + Int, serial stream #= 0.063 +- 1.3 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10000 elements +collection.mutable.ArrayBuffer + Int, base collection 0.000 +- 3.5 % + Int, iterator on coll #= 0.067 +- 13.3 % + Int, serial stream #- 0.056 +- 1.9 % + +map/filter/take trio +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.7 % + Int, iterator on coll ## 0.084 +- 10.5 % + Int, serial stream #= 0.063 +- 1.0 % + +map/filter/take trio +10000 elements +collection.mutable.ArraySeq + Int, base collection 0.000 +- 2.3 % + Int, iterator on coll #= 0.062 +- 0.4 % + Int, serial stream #- 0.056 +- 1.1 % + +map/filter/take trio +10000 elements +collection.mutable.ArrayStack + Int, base collection 0.000 +- 8.5 % + Int, iterator on coll ## 0.080 +- 17.5 % + Int, serial stream #- 0.053 +- 2.6 % + +map/filter/take trio +10000 elements +java.util.ArrayList + Int, serial stream # 0.042 +- 4.4 % + +map/filter/take trio +10000 elements +java.util.LinkedList + Int, serial stream # 0.041 +- 5.9 % + +map/filter/take trio +10000 elements +collection.immutable.List + Int, base collection 0.000 +- 1.0 % + Int, iterator on coll #= 0.072 +- 0.8 % + Int, serial stream #- 0.055 +- 10.6 % + +map/filter/take trio +10000 elements +collection.mutable.Queue + Int, base collection 0.000 +- 3.2 % + Int, iterator on coll #- 0.053 +- 28.4 % + Int, serial stream - 0.018 +- 1.7 % + +map/filter/take trio +10000 elements +collection.immutable.Queue + Int, base collection 0.000 +- 1.4 % + Int, iterator on coll ## 0.076 +- 10.0 % + Int, serial stream # 0.037 +- 1.2 % + +map/filter/take trio +10000 elements +collection.immutable.Stream + Int, base collection - 0.009 +- 6.4 % + Int, iterator on coll = 0.026 +- 4.1 % + Int, serial stream #- 0.056 +- 0.8 % + +map/filter/take trio +10000 elements +collection.immutable.Vector + Int, base collection 0.000 +- 2.0 % + Int, iterator on coll ## 0.082 +- 15.8 % + Int, serial stream #- 0.055 +- 3.9 % + +map/filter/take trio +10000 elements +collection.mutable.WrappedArray + Int, base collection 0.000 +- 8.8 % + Int, iterator on coll #- 0.053 +- 1.3 % + Int, serial stream #- 0.049 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10 elements +collection.mutable.ArrayBuffer + String, base collection ############ 0.485 +- 0.8 % + String, iterator on coll #############- 0.531 +- 1.1 % + String, serial stream ############= 0.502 +- 3.1 % + +map/filter/take trio +10 elements +Array + String, base collection ######################### 1.000 +- 0.6 % + String, iterator on coll #############- 0.527 +- 1.7 % + String, serial stream ############# 0.516 +- 1.0 % + +map/filter/take trio +10 elements +collection.mutable.ArraySeq + String, base collection ##########- 0.414 +- 0.9 % + String, iterator on coll ############= 0.509 +- 3.8 % + String, serial stream #############= 0.545 +- 12.0 % + +map/filter/take trio +10 elements +collection.mutable.ArrayStack + String, base collection ########- 0.335 +- 1.8 % + String, iterator on coll #############= 0.551 +- 10.2 % + String, serial stream #############- 0.531 +- 10.7 % + +map/filter/take trio +10 elements +java.util.ArrayList + String, serial stream ############ 0.477 +- 2.2 % + +map/filter/take trio +10 elements +java.util.LinkedList + String, serial stream ############- 0.487 +- 5.2 % + +map/filter/take trio +10 elements +collection.immutable.List + String, base collection #############= 0.547 +- 5.1 % + String, iterator on coll ##############= 0.589 +- 1.4 % + String, serial stream #############- 0.528 +- 13.5 % + +map/filter/take trio +10 elements +collection.mutable.Queue + String, base collection ###### 0.235 +- 3.4 % + String, iterator on coll #############- 0.531 +- 1.2 % + String, serial stream #########= 0.389 +- 9.1 % + +map/filter/take trio +10 elements +collection.immutable.Queue + String, base collection ########- 0.336 +- 1.1 % + String, iterator on coll ##############= 0.589 +- 1.3 % + String, serial stream ###########- 0.458 +- 2.1 % + +map/filter/take trio +10 elements +collection.immutable.Stream + String, base collection ######- 0.250 +- 2.5 % + String, iterator on coll ##########- 0.415 +- 2.0 % + String, serial stream #############= 0.546 +- 12.1 % + +map/filter/take trio +10 elements +collection.immutable.Vector + String, base collection ############= 0.512 +- 6.6 % + String, iterator on coll ############# 0.525 +- 1.2 % + String, serial stream ############- 0.496 +- 1.0 % + +map/filter/take trio +10 elements +collection.mutable.WrappedArray + String, base collection ###########= 0.472 +- 4.5 % + String, iterator on coll #############- 0.527 +- 2.6 % + String, serial stream ############- 0.500 +- 1.0 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +map/filter/take trio +10000 elements +collection.mutable.ArrayBuffer + String, base collection 0.000 +- 9.2 % + String, iterator on coll ############## 0.555 +- 1.4 % + String, serial stream #############- 0.530 +- 1.4 % + +map/filter/take trio +10000 elements +Array + String, base collection ######################### 1.000 +- 8.4 % + String, iterator on coll #############= 0.542 +- 1.1 % + String, serial stream #############= 0.549 +- 3.1 % + +map/filter/take trio +10000 elements +collection.mutable.ArraySeq + String, base collection 0.000 +- 6.2 % + String, iterator on coll #############= 0.550 +- 2.2 % + String, serial stream ##############- 0.571 +- 12.9 % + +map/filter/take trio +10000 elements +collection.mutable.ArrayStack + String, base collection 0.000 +- 6.9 % + String, iterator on coll ###############= 0.624 +- 7.3 % + String, serial stream ############# 0.516 +- 1.8 % + +map/filter/take trio +10000 elements +java.util.ArrayList + String, serial stream ############# 0.522 +- 4.9 % + +map/filter/take trio +10000 elements +java.util.LinkedList + String, serial stream ############= 0.511 +- 1.6 % + +map/filter/take trio +10000 elements +collection.immutable.List + String, base collection 0.001 +- 9.9 % + String, iterator on coll ############### 0.600 +- 2.1 % + String, serial stream ############## 0.554 +- 5.2 % + +map/filter/take trio +10000 elements +collection.mutable.Queue + String, base collection 0.000 +- 7.9 % + String, iterator on coll ############## 0.562 +- 1.2 % + String, serial stream ########## 0.396 +- 9.2 % + +map/filter/take trio +10000 elements +collection.immutable.Queue + String, base collection 0.000 +- 3.8 % + String, iterator on coll ##############= 0.590 +- 2.3 % + String, serial stream #############= 0.546 +- 13.1 % + +map/filter/take trio +10000 elements +collection.immutable.Stream + String, base collection ######= 0.273 +- 2.0 % + String, iterator on coll ###########- 0.458 +- 3.7 % + String, serial stream ############### 0.606 +- 11.6 % + +map/filter/take trio +10000 elements +collection.immutable.Vector + String, base collection 0.001 +- 8.4 % + String, iterator on coll ############# 0.521 +- 1.4 % + String, serial stream #############= 0.540 +- 4.6 % + +map/filter/take trio +10000 elements +collection.mutable.WrappedArray + String, base collection 0.001 +- 1.7 % + String, iterator on coll #############= 0.544 +- 2.2 % + String, serial stream #############= 0.543 +- 3.3 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast sum of lengths +10 elements +collection.mutable.ArrayBuffer + String, base collection ########- 0.332 +- 0.8 % + String, iterator on coll ######## 0.316 +- 2.1 % + String, serial stream ######## 0.318 +- 1.3 % + String Stepper (can par) ##############= 0.582 +- 0.4 % + +fast sum of lengths +10 elements +Array + String, base collection ######################### 1.000 +- 0.4 % + String, iterator on coll #######- 0.287 +- 15.1 % + String, serial stream ######## 0.325 +- 1.5 % + String Stepper (can par) ################# 0.686 +- 0.4 % + +fast sum of lengths +10 elements +collection.mutable.ArraySeq + String, base collection ##################- 0.731 +- 1.2 % + String, iterator on coll ######## 0.319 +- 0.5 % + String, serial stream ######## 0.319 +- 0.6 % + String Stepper (can par) ##############= 0.582 +- 0.3 % + +fast sum of lengths +10 elements +collection.mutable.ArrayStack + String, base collection ##################- 0.729 +- 1.5 % + String, iterator on coll ########= 0.344 +- 1.0 % + String, serial stream ####### 0.282 +- 3.0 % + String Stepper (seq only) ############# 0.519 +- 9.1 % + +fast sum of lengths +10 elements +collection.immutable.ListSet + String, base collection #####- 0.219 +- 0.4 % + String, iterator on coll ####### 0.285 +- 0.9 % + String, serial stream ####- 0.179 +- 5.8 % + String Stepper (seq only) ########## 0.394 +- 1.2 % + +fast sum of lengths +10 elements +collection.immutable.HashSet + String, base collection ######= 0.266 +- 11.3 % + String, iterator on coll ####### 0.277 +- 11.4 % + String, serial stream #### 0.161 +- 1.3 % + String Stepper (can par) #####= 0.221 +- 3.2 % + +fast sum of lengths +10 elements +java.util.ArrayList + String, serial stream ########- 0.337 +- 0.4 % + +fast sum of lengths +10 elements +java.util.LinkedList + String, serial stream ######## 0.314 +- 1.6 % + +fast sum of lengths +10 elements +collection.mutable.LinkedHashSet + String, base collection ################= 0.668 +- 1.1 % + String, iterator on coll #########- 0.370 +- 0.9 % + String, serial stream #######- 0.292 +- 0.8 % + String Stepper (seq only) ############- 0.495 +- 0.9 % + +fast sum of lengths +10 elements +collection.immutable.List + String, base collection ###############- 0.613 +- 1.3 % + String, iterator on coll ########= 0.343 +- 0.4 % + String, serial stream #####- 0.214 +- 2.0 % + String Stepper (seq only) ########- 0.339 +- 2.4 % + +fast sum of lengths +10 elements +collection.mutable.HashSet + String, base collection ###########- 0.458 +- 4.6 % + String, iterator on coll ######- 0.248 +- 0.7 % + String, serial stream ##### 0.199 +- 0.9 % + String Stepper (can par) ##########= 0.432 +- 1.4 % + +fast sum of lengths +10 elements +collection.mutable.Queue + String, base collection ## 0.086 +- 0.8 % + String, iterator on coll ###### 0.245 +- 0.4 % + String, serial stream #= 0.069 +- 1.0 % + String Stepper (seq only) ## 0.084 +- 1.8 % + +fast sum of lengths +10 elements +collection.mutable.PriorityQueue + String, base collection ######## 0.314 +- 0.3 % + String, iterator on coll ######## 0.322 +- 0.5 % + String, serial stream ####### 0.285 +- 1.3 % + String Stepper (seq only) ############= 0.505 +- 0.8 % + +fast sum of lengths +10 elements +collection.immutable.Queue + String, base collection #####= 0.232 +- 0.4 % + String, iterator on coll ########- 0.330 +- 0.7 % + String, serial stream #### 0.166 +- 0.9 % + String Stepper (seq only) #####= 0.231 +- 1.1 % + +fast sum of lengths +10 elements +collection.immutable.Stream + String, base collection ###############= 0.629 +- 0.7 % + String, iterator on coll ## 0.087 +- 4.7 % + String, serial stream #####- 0.219 +- 1.6 % + String Stepper (seq only) ########- 0.331 +- 1.0 % + +fast sum of lengths +10 elements +collection.immutable.TreeSet + String, base collection ########- 0.338 +- 0.4 % + String, iterator on coll #####= 0.224 +- 0.7 % + String, serial stream ####- 0.173 +- 1.6 % + String Stepper (seq only) ######- 0.255 +- 3.4 % + +fast sum of lengths +10 elements +collection.immutable.Vector + String, base collection ####### 0.276 +- 0.5 % + String, iterator on coll #######= 0.307 +- 0.5 % + String, serial stream ###### 0.236 +- 1.2 % + String Stepper (can par) ##########- 0.418 +- 0.6 % + +fast sum of lengths +10 elements +collection.mutable.WrappedArray + String, base collection ########= 0.344 +- 0.3 % + String, iterator on coll ########- 0.329 +- 0.3 % + String, serial stream ######## 0.317 +- 0.5 % + String Stepper (can par) ##############= 0.583 +- 1.4 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast sum of lengths +10000 elements +collection.mutable.ArrayBuffer + String, base collection ########= 0.340 +- 0.9 % + String, iterator on coll ########- 0.334 +- 0.3 % + String, serial stream #################- 0.690 +- 33.6 % + String Stepper (can par) ############# 0.526 +- 2.1 % + +fast sum of lengths +10000 elements +Array + String, base collection ######################### 1.000 +- 0.6 % + String, iterator on coll ########- 0.328 +- 0.9 % + String, serial stream ################## 0.726 +- 27.9 % + String Stepper (can par) ################ 0.640 +- 4.6 % + +fast sum of lengths +10000 elements +collection.mutable.ArraySeq + String, base collection ####################= 0.830 +- 0.7 % + String, iterator on coll ########- 0.332 +- 0.4 % + String, serial stream ###################- 0.774 +- 24.4 % + String Stepper (can par) ############# 0.523 +- 1.9 % + +fast sum of lengths +10000 elements +collection.mutable.ArrayStack + String, base collection ################- 0.654 +- 6.7 % + String, iterator on coll ######### 0.362 +- 0.3 % + String, serial stream ################= 0.666 +- 25.4 % + String Stepper (seq only) ############# 0.515 +- 9.1 % + +fast sum of lengths +10000 elements +collection.immutable.ListSet + String, base collection #########- 0.379 +- 30.0 % + String, iterator on coll ######## 0.325 +- 16.5 % + String, serial stream ########### 0.436 +- 39.9 % + String Stepper (seq only) #########- 0.372 +- 6.0 % + +fast sum of lengths +10000 elements +collection.immutable.HashSet + String, base collection ### 0.125 +- 3.1 % + String, iterator on coll ### 0.123 +- 1.0 % + String, serial stream ### 0.118 +- 0.5 % + String Stepper (can par) ###- 0.135 +- 0.6 % + +fast sum of lengths +10000 elements +java.util.ArrayList + String, serial stream ####################= 0.821 +- 10.1 % + +fast sum of lengths +10000 elements +java.util.LinkedList + String, serial stream ################### 0.755 +- 3.9 % + +fast sum of lengths +10000 elements +collection.mutable.LinkedHashSet + String, base collection #################- 0.691 +- 2.3 % + String, iterator on coll ##########- 0.412 +- 11.4 % + String, serial stream #############= 0.551 +- 30.5 % + String Stepper (seq only) ########## 0.402 +- 3.8 % + +fast sum of lengths +10000 elements +collection.immutable.List + String, base collection #################= 0.713 +- 1.4 % + String, iterator on coll #########- 0.372 +- 11.2 % + String, serial stream ###########- 0.459 +- 0.6 % + String Stepper (seq only) #######= 0.304 +- 1.5 % + +fast sum of lengths +10000 elements +collection.mutable.HashSet + String, base collection ###- 0.127 +- 0.2 % + String, iterator on coll ##= 0.113 +- 0.3 % + String, serial stream ## 0.086 +- 0.4 % + String Stepper (can par) ###- 0.133 +- 0.9 % + +fast sum of lengths +10000 elements +collection.mutable.Queue + String, base collection #= 0.072 +- 1.4 % + String, iterator on coll #########- 0.367 +- 26.7 % + String, serial stream ### 0.115 +- 1.7 % + String Stepper (seq only) ## 0.080 +- 1.2 % + +fast sum of lengths +10000 elements +collection.mutable.PriorityQueue + String, base collection ########- 0.338 +- 30.0 % + String, iterator on coll ######## 0.319 +- 30.9 % + String, serial stream #### 0.166 +- 16.9 % + String Stepper (seq only) ###### 0.243 +- 5.6 % + +fast sum of lengths +10000 elements +collection.immutable.Queue + String, base collection #########= 0.381 +- 32.4 % + String, iterator on coll ########## 0.399 +- 11.0 % + String, serial stream ######- 0.254 +- 2.7 % + String Stepper (seq only) #####= 0.220 +- 0.8 % + +fast sum of lengths +10000 elements +collection.immutable.Stream + String, base collection #######- 0.287 +- 4.8 % + String, iterator on coll ##- 0.095 +- 7.2 % + String, serial stream #####= 0.220 +- 8.0 % + String Stepper (seq only) ######- 0.258 +- 1.7 % + +fast sum of lengths +10000 elements +collection.immutable.TreeSet + String, base collection ####= 0.180 +- 0.7 % + String, iterator on coll ##### 0.194 +- 8.2 % + String, serial stream ##= 0.110 +- 0.9 % + String Stepper (seq only) ####= 0.190 +- 2.3 % + +fast sum of lengths +10000 elements +collection.immutable.Vector + String, base collection ##########- 0.412 +- 15.0 % + String, iterator on coll ######### 0.355 +- 22.0 % + String, serial stream ###########= 0.460 +- 16.9 % + String Stepper (can par) ###########- 0.452 +- 3.0 % + +fast sum of lengths +10000 elements +collection.mutable.WrappedArray + String, base collection ########= 0.353 +- 0.3 % + String, iterator on coll ########- 0.340 +- 0.8 % + String, serial stream ################# 0.683 +- 32.7 % + String Stepper (can par) #############- 0.533 +- 2.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + Int, par collection ########################- 0.968 +- 3.4 % + Int, parallel stream ##############################~~# 4.299 +- 2.7 % + +parallel filter/map/sum trio +10 elements +Array + Int, par collection ######################### 1.000 +- 2.1 % + Int, parallel stream ##############################~~# 4.361 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.mutable.ArraySeq + Int, par collection #########################- 1.014 +- 1.2 % + Int, parallel stream ##############################~~# 4.362 +- 2.0 % + +parallel filter/map/sum trio +10 elements +collection.immutable.HashSet + Int, par collection ####################= 0.830 +- 2.2 % + Int, parallel stream ##############################~~# 3.569 +- 1.5 % + +parallel filter/map/sum trio +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 4.389 +- 1.1 % + +parallel filter/map/sum trio +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 4.299 +- 2.4 % + +parallel filter/map/sum trio +10 elements +collection.mutable.HashSet + Int, par collection ########################### 1.079 +- 1.1 % + Int, parallel stream ##############################~~# 5.277 +- 2.3 % + +parallel filter/map/sum trio +10 elements +collection.immutable.Vector + Int, par collection #####################- 0.847 +- 1.7 % + Int, parallel stream ##############################~~# 4.289 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.mutable.WrappedArray + Int, par collection ######################### 1.003 +- 1.4 % + Int, parallel stream ##############################~~# 4.399 +- 0.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ##############################~~# 1.469 +- 1.3 % + Int, parallel stream ##############################~~# 6.310 +- 10.2 % + +parallel filter/map/sum trio +10000 elements +Array + Int, par collection ######################### 1.000 +- 1.0 % + Int, parallel stream ##############################~~# 11.043 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + Int, par collection ##############################~~# 1.469 +- 1.5 % + Int, parallel stream ##############################~~# 6.301 +- 4.2 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.HashSet + Int, par collection ################= 0.664 +- 0.8 % + Int, parallel stream ##############################~~# 3.468 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 9.264 +- 3.0 % + +parallel filter/map/sum trio +10000 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 4.247 +- 10.6 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.HashSet + Int, par collection ################## 0.727 +- 1.2 % + Int, parallel stream ##############################~~# 3.579 +- 7.4 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.Vector + Int, par collection ##############################- 1.216 +- 2.2 % + Int, parallel stream ##############################~~# 5.987 +- 3.6 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + Int, par collection ########################### 1.074 +- 1.1 % + Int, parallel stream ##############################~~# 5.150 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10 elements +collection.mutable.ArrayBuffer + String, par collection #########################- 1.014 +- 0.8 % + String, parallel stream ##############################~~# 4.219 +- 3.2 % + +parallel filter/map/sum trio +10 elements +Array + String, par collection ######################### 1.000 +- 2.8 % + String, parallel stream ##############################~~# 4.299 +- 1.1 % + +parallel filter/map/sum trio +10 elements +collection.mutable.ArraySeq + String, par collection ######################### 1.002 +- 1.6 % + String, parallel stream ##############################~~# 4.326 +- 1.5 % + +parallel filter/map/sum trio +10 elements +collection.immutable.HashSet + String, par collection #####################= 0.861 +- 1.1 % + String, parallel stream ##############################~~# 3.656 +- 1.1 % + +parallel filter/map/sum trio +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 4.173 +- 3.2 % + +parallel filter/map/sum trio +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 4.073 +- 3.0 % + +parallel filter/map/sum trio +10 elements +collection.mutable.HashSet + String, par collection ######################## 0.964 +- 1.3 % + String, parallel stream ##############################~~# 4.613 +- 1.2 % + +parallel filter/map/sum trio +10 elements +collection.immutable.Vector + String, par collection #####################- 0.857 +- 1.2 % + String, parallel stream ##############################~~# 4.221 +- 1.6 % + +parallel filter/map/sum trio +10 elements +collection.mutable.WrappedArray + String, par collection ########################= 0.982 +- 2.7 % + String, parallel stream ##############################~~# 4.370 +- 1.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +parallel filter/map/sum trio +10000 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 0.994 +- 1.4 % + String, parallel stream ##############################~~# 5.317 +- 7.5 % + +parallel filter/map/sum trio +10000 elements +Array + String, par collection ######################### 1.000 +- 1.3 % + String, parallel stream ##############################~~# 6.147 +- 1.0 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.ArraySeq + String, par collection ######################### 1.004 +- 1.5 % + String, parallel stream ##############################~~# 5.464 +- 5.9 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.HashSet + String, par collection ########### 0.434 +- 2.2 % + String, parallel stream ##############################~~# 2.221 +- 6.4 % + +parallel filter/map/sum trio +10000 elements +java.util.ArrayList + String, parallel stream ##############################~~# 6.477 +- 0.4 % + +parallel filter/map/sum trio +10000 elements +java.util.LinkedList + String, parallel stream ##############################~~# 2.252 +- 10.3 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.HashSet + String, par collection ###########= 0.470 +- 0.9 % + String, parallel stream ##############################~~# 2.477 +- 8.0 % + +parallel filter/map/sum trio +10000 elements +collection.immutable.Vector + String, par collection ###################= 0.786 +- 0.7 % + String, parallel stream ##############################~~# 5.795 +- 1.1 % + +parallel filter/map/sum trio +10000 elements +collection.mutable.WrappedArray + String, par collection ########################= 0.985 +- 1.7 % + String, parallel stream ##############################~~# 5.575 +- 5.4 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trig on hashCode +10 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 0.999 +- 1.3 % + String, parallel stream ##############################~~# 3.106 +- 0.7 % + +slow parallel trig on hashCode +10 elements +Array + String, par collection ######################### 1.000 +- 1.1 % + String, parallel stream ##############################~~# 3.144 +- 0.8 % + +slow parallel trig on hashCode +10 elements +collection.mutable.ArraySeq + String, par collection #########################- 1.016 +- 1.1 % + String, parallel stream ##############################~~# 3.117 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.immutable.HashSet + String, par collection ################ 0.638 +- 1.3 % + String, parallel stream ##############################~~# 2.879 +- 0.6 % + +slow parallel trig on hashCode +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 3.144 +- 0.7 % + +slow parallel trig on hashCode +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 3.126 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.mutable.HashSet + String, par collection #######################- 0.937 +- 1.0 % + String, parallel stream ##############################~~# 2.938 +- 0.5 % + +slow parallel trig on hashCode +10 elements +collection.immutable.Vector + String, par collection ##################= 0.741 +- 1.5 % + String, parallel stream ##############################~~# 3.139 +- 1.0 % + +slow parallel trig on hashCode +10 elements +collection.mutable.WrappedArray + String, par collection ######################### 1.000 +- 1.0 % + String, parallel stream ##############################~~# 3.104 +- 1.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trig on hashCode +10000 elements +collection.mutable.ArrayBuffer + String, par collection ########################- 0.978 +- 2.1 % + String, parallel stream ##############################- 1.209 +- 0.9 % + +slow parallel trig on hashCode +10000 elements +Array + String, par collection ######################### 1.000 +- 0.9 % + String, parallel stream ##############################- 1.211 +- 0.9 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.ArraySeq + String, par collection ########################- 0.975 +- 2.2 % + String, parallel stream ##############################- 1.215 +- 0.7 % + +slow parallel trig on hashCode +10000 elements +collection.immutable.HashSet + String, par collection ####################- 0.809 +- 1.9 % + String, parallel stream ############################- 1.129 +- 0.5 % + +slow parallel trig on hashCode +10000 elements +java.util.ArrayList + String, parallel stream ############################## 1.200 +- 2.0 % + +slow parallel trig on hashCode +10000 elements +java.util.LinkedList + String, parallel stream ############################ 1.121 +- 0.6 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.HashSet + String, par collection ##################- 0.734 +- 1.8 % + String, parallel stream #############################- 1.176 +- 0.4 % + +slow parallel trig on hashCode +10000 elements +collection.immutable.Vector + String, par collection #################- 0.698 +- 1.3 % + String, parallel stream ##############################- 1.216 +- 0.6 % + +slow parallel trig on hashCode +10000 elements +collection.mutable.WrappedArray + String, par collection ########################- 0.969 +- 2.4 % + String, parallel stream ##############################- 1.213 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel sum of lengths +10 elements +collection.mutable.ArrayBuffer + String, par collection ########################## 1.036 +- 6.6 % + String, parallel stream ##############################~~# 1.759 +- 1.2 % + +fast parallel sum of lengths +10 elements +Array + String, par collection ######################### 1.000 +- 6.4 % + String, parallel stream ##############################~~# 1.740 +- 1.8 % + +fast parallel sum of lengths +10 elements +collection.mutable.ArraySeq + String, par collection ###########################- 1.099 +- 12.3 % + String, parallel stream ##############################~~# 1.748 +- 2.1 % + +fast parallel sum of lengths +10 elements +collection.immutable.HashSet + String, par collection #########################- 1.019 +- 2.9 % + String, parallel stream ##############################~~# 1.470 +- 1.1 % + +fast parallel sum of lengths +10 elements +java.util.ArrayList + String, parallel stream ##############################~~# 1.729 +- 1.0 % + +fast parallel sum of lengths +10 elements +java.util.LinkedList + String, parallel stream ##############################~~# 1.690 +- 1.4 % + +fast parallel sum of lengths +10 elements +collection.mutable.HashSet + String, par collection ###########################- 1.092 +- 3.1 % + String, parallel stream ##############################~~# 1.902 +- 3.4 % + +fast parallel sum of lengths +10 elements +collection.immutable.Vector + String, par collection ######################= 0.908 +- 3.1 % + String, parallel stream ##############################~~# 1.761 +- 1.4 % + +fast parallel sum of lengths +10 elements +collection.mutable.WrappedArray + String, par collection #########################= 1.032 +- 10.0 % + String, parallel stream ##############################~~# 1.751 +- 1.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel sum of lengths +10000 elements +collection.mutable.ArrayBuffer + String, par collection ######################### 1.002 +- 1.0 % + String, parallel stream ############################ 1.122 +- 0.9 % + +fast parallel sum of lengths +10000 elements +Array + String, par collection ######################### 1.000 +- 0.9 % + String, parallel stream ################################ 1.284 +- 1.7 % + +fast parallel sum of lengths +10000 elements +collection.mutable.ArraySeq + String, par collection ########################= 0.992 +- 1.6 % + String, parallel stream ################################- 1.287 +- 6.4 % + +fast parallel sum of lengths +10000 elements +collection.immutable.HashSet + String, par collection ##########- 0.408 +- 0.9 % + String, parallel stream ################- 0.648 +- 0.6 % + +fast parallel sum of lengths +10000 elements +java.util.ArrayList + String, parallel stream ##############################~~# 1.432 +- 13.1 % + +fast parallel sum of lengths +10000 elements +java.util.LinkedList + String, parallel stream #############= 0.550 +- 12.9 % + +fast parallel sum of lengths +10000 elements +collection.mutable.HashSet + String, par collection ##########- 0.411 +- 0.8 % + String, parallel stream ##############= 0.583 +- 0.6 % + +fast parallel sum of lengths +10000 elements +collection.immutable.Vector + String, par collection ################### 0.759 +- 1.2 % + String, parallel stream ##############################= 1.221 +- 0.8 % + +fast parallel sum of lengths +10000 elements +collection.mutable.WrappedArray + String, par collection ######################### 0.999 +- 1.0 % + String, parallel stream ################################- 1.294 +- 7.0 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel summation +10 elements +collection.mutable.ArrayBuffer + Int, par collection ######################- 0.890 +- 6.7 % + Int, parallel stream ##############################~~# 1.483 +- 1.2 % + +fast parallel summation +10 elements +Array + Int, par collection ######################### 1.000 +- 6.0 % + Int, parallel stream ##############################~~# 1.467 +- 1.2 % + +fast parallel summation +10 elements +collection.mutable.ArraySeq + Int, par collection ######################= 0.904 +- 6.7 % + Int, parallel stream ##############################~~# 1.471 +- 1.4 % + +fast parallel summation +10 elements +collection.immutable.HashSet + Int, par collection ##################- 0.737 +- 5.1 % + Int, parallel stream ###############################- 1.257 +- 1.4 % + +fast parallel summation +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 1.497 +- 1.0 % + +fast parallel summation +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 1.463 +- 1.4 % + +fast parallel summation +10 elements +collection.mutable.HashSet + Int, par collection ##########################- 1.060 +- 1.0 % + Int, parallel stream ##############################~~# 1.800 +- 1.4 % + +fast parallel summation +10 elements +collection.immutable.Vector + Int, par collection ####################= 0.829 +- 0.7 % + Int, parallel stream ##############################~~# 1.459 +- 2.1 % + +fast parallel summation +10 elements +collection.mutable.WrappedArray + Int, par collection #########################- 1.008 +- 7.5 % + Int, parallel stream ##############################~~# 1.489 +- 0.8 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast parallel summation +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ##############################~~# 2.489 +- 0.8 % + Int, parallel stream ##############################~~# 3.404 +- 1.4 % + +fast parallel summation +10000 elements +Array + Int, par collection ######################### 1.000 +- 9.6 % + Int, parallel stream ##############################~~# 6.862 +- 4.9 % + +fast parallel summation +10000 elements +collection.mutable.ArraySeq + Int, par collection ##############################~~# 2.482 +- 0.8 % + Int, parallel stream ##############################~~# 3.686 +- 0.8 % + +fast parallel summation +10000 elements +collection.immutable.HashSet + Int, par collection ################################- 1.300 +- 1.0 % + Int, parallel stream ##############################~~# 1.898 +- 0.5 % + +fast parallel summation +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 5.781 +- 16.3 % + +fast parallel summation +10000 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 2.435 +- 8.6 % + +fast parallel summation +10000 elements +collection.mutable.HashSet + Int, par collection ###############################- 1.259 +- 0.9 % + Int, parallel stream ##############################~~# 1.749 +- 0.4 % + +fast parallel summation +10000 elements +collection.immutable.Vector + Int, par collection ##############################~~# 1.993 +- 1.1 % + Int, parallel stream ##############################~~# 3.596 +- 0.9 % + +fast parallel summation +10000 elements +collection.mutable.WrappedArray + Int, par collection ###############################= 1.272 +- 4.8 % + Int, parallel stream ##############################~~# 2.706 +- 0.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trigonometry +10 elements +collection.mutable.ArrayBuffer + Int, par collection ######################### 0.999 +- 1.6 % + Int, parallel stream ##############################~~# 3.251 +- 0.9 % + +slow parallel trigonometry +10 elements +Array + Int, par collection ######################### 1.000 +- 1.0 % + Int, parallel stream ##############################~~# 3.257 +- 0.6 % + +slow parallel trigonometry +10 elements +collection.mutable.ArraySeq + Int, par collection #########################- 1.009 +- 1.4 % + Int, parallel stream ##############################~~# 3.252 +- 0.9 % + +slow parallel trigonometry +10 elements +collection.immutable.HashSet + Int, par collection ###############- 0.610 +- 1.2 % + Int, parallel stream ##############################~~# 2.825 +- 0.9 % + +slow parallel trigonometry +10 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 3.210 +- 1.3 % + +slow parallel trigonometry +10 elements +java.util.LinkedList + Int, parallel stream ##############################~~# 3.196 +- 0.4 % + +slow parallel trigonometry +10 elements +collection.mutable.HashSet + Int, par collection ########################- 0.969 +- 2.4 % + Int, parallel stream ##############################~~# 3.086 +- 0.4 % + +slow parallel trigonometry +10 elements +collection.immutable.Vector + Int, par collection ################## 0.721 +- 2.2 % + Int, parallel stream ##############################~~# 3.180 +- 0.9 % + +slow parallel trigonometry +10 elements +collection.mutable.WrappedArray + Int, par collection ######################### 1.000 +- 1.1 % + Int, parallel stream ##############################~~# 3.259 +- 1.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow parallel trigonometry +10000 elements +collection.mutable.ArrayBuffer + Int, par collection ###########################- 1.096 +- 0.7 % + Int, parallel stream ##############################~~# 1.369 +- 0.5 % + +slow parallel trigonometry +10000 elements +Array + Int, par collection ######################### 1.000 +- 2.1 % + Int, parallel stream ##############################~~# 1.385 +- 0.7 % + +slow parallel trigonometry +10000 elements +collection.mutable.ArraySeq + Int, par collection ########################### 1.078 +- 2.1 % + Int, parallel stream ##############################~~# 1.347 +- 2.6 % + +slow parallel trigonometry +10000 elements +collection.immutable.HashSet + Int, par collection #####################- 0.854 +- 2.2 % + Int, parallel stream ################################- 1.290 +- 0.7 % + +slow parallel trigonometry +10000 elements +java.util.ArrayList + Int, parallel stream ##############################~~# 1.381 +- 0.9 % + +slow parallel trigonometry +10000 elements +java.util.LinkedList + Int, parallel stream ###############################= 1.273 +- 0.6 % + +slow parallel trigonometry +10000 elements +collection.mutable.HashSet + Int, par collection ##################- 0.731 +- 3.7 % + Int, parallel stream ##############################~~# 1.338 +- 0.5 % + +slow parallel trigonometry +10000 elements +collection.immutable.Vector + Int, par collection #################- 0.699 +- 1.7 % + Int, parallel stream ##############################~~# 1.358 +- 1.2 % + +slow parallel trigonometry +10000 elements +collection.mutable.WrappedArray + Int, par collection #########################- 1.018 +- 2.1 % + Int, parallel stream ##############################~~# 1.356 +- 0.7 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast summation +10 elements +collection.mutable.ArrayBuffer + Int, base collection #### 0.162 +- 4.7 % + Int, iterator on coll ### 0.121 +- 1.4 % + Int, serial stream ## 0.086 +- 2.3 % + Int Stepper (can par) ###### 0.236 +- 1.3 % + +fast summation +10 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ##- 0.097 +- 2.3 % + Int, serial stream #####- 0.217 +- 1.0 % + Int Stepper (can par) #####################- 0.855 +- 0.3 % + +fast summation +10 elements +collection.mutable.ArraySeq + Int, base collection ####- 0.167 +- 0.3 % + Int, iterator on coll ###- 0.140 +- 2.3 % + Int, serial stream ## 0.084 +- 4.9 % + Int Stepper (can par) #############= 0.552 +- 0.4 % + +fast summation +10 elements +collection.mutable.ArrayStack + Int, base collection ####- 0.169 +- 4.1 % + Int, iterator on coll #### 0.157 +- 2.3 % + Int, serial stream ## 0.074 +- 4.7 % + Int Stepper (seq only) ######- 0.258 +- 1.3 % + +fast summation +10 elements +collection.immutable.ListSet + Int, base collection ##= 0.107 +- 0.9 % + Int, iterator on coll #### 0.163 +- 1.3 % + Int, serial stream ###= 0.140 +- 2.2 % + Int Stepper (seq only) ##= 0.111 +- 18.1 % + +fast summation +10 elements +collection.immutable.HashSet + Int, base collection ###= 0.148 +- 3.7 % + Int, iterator on coll ## 0.086 +- 0.8 % + Int, serial stream ### 0.120 +- 1.1 % + Int Stepper (can par) ### 0.119 +- 4.0 % + +fast summation +10 elements +java.util.ArrayList + Int, serial stream #####= 0.232 +- 0.6 % + +fast summation +10 elements +java.util.LinkedList + Int, serial stream #####- 0.214 +- 0.5 % + +fast summation +10 elements +collection.mutable.LinkedHashSet + Int, base collection #### 0.159 +- 5.0 % + Int, iterator on coll #### 0.157 +- 2.3 % + Int, serial stream ## 0.080 +- 2.9 % + Int Stepper (seq only) ####- 0.168 +- 0.5 % + +fast summation +10 elements +collection.immutable.List + Int, base collection ######= 0.263 +- 0.2 % + Int, iterator on coll #### 0.155 +- 1.4 % + Int, serial stream ### 0.121 +- 2.4 % + Int Stepper (seq only) ### 0.117 +- 2.1 % + +fast summation +10 elements +collection.mutable.HashSet + Int, base collection ##= 0.109 +- 2.1 % + Int, iterator on coll #= 0.070 +- 0.3 % + Int, serial stream ##- 0.093 +- 0.8 % + Int Stepper (can par) #######= 0.308 +- 0.5 % + +fast summation +10 elements +collection.mutable.Queue + Int, base collection # 0.041 +- 0.8 % + Int, iterator on coll ##- 0.088 +- 0.3 % + Int, serial stream # 0.034 +- 7.5 % + Int Stepper (seq only) #- 0.055 +- 0.8 % + +fast summation +10 elements +collection.mutable.PriorityQueue + Int, base collection ##= 0.104 +- 2.7 % + Int, iterator on coll ###- 0.133 +- 2.1 % + Int, serial stream #= 0.073 +- 2.1 % + Int Stepper (seq only) ###- 0.136 +- 0.4 % + +fast summation +10 elements +collection.immutable.Queue + Int, base collection ##= 0.108 +- 0.7 % + Int, iterator on coll ###= 0.146 +- 0.8 % + Int, serial stream ## 0.081 +- 18.1 % + Int Stepper (seq only) #- 0.058 +- 1.4 % + +fast summation +10 elements +collection.immutable.Stream + Int, base collection ######= 0.261 +- 0.2 % + Int, iterator on coll # 0.035 +- 5.4 % + Int, serial stream ### 0.116 +- 1.7 % + Int Stepper (seq only) ##= 0.113 +- 0.3 % + +fast summation +10 elements +collection.immutable.TreeSet + Int, base collection #### 0.166 +- 0.6 % + Int, iterator on coll ## 0.081 +- 0.6 % + Int, serial stream ##= 0.102 +- 1.5 % + Int Stepper (seq only) ##- 0.097 +- 0.3 % + +fast summation +10 elements +collection.immutable.Vector + Int, base collection ##= 0.104 +- 0.5 % + Int, iterator on coll ###- 0.130 +- 2.2 % + Int, serial stream ## 0.078 +- 2.1 % + Int Stepper (can par) ######### 0.359 +- 0.8 % + +fast summation +10 elements +collection.mutable.WrappedArray + Int, base collection ###= 0.141 +- 0.3 % + Int, iterator on coll ##- 0.096 +- 5.1 % + Int, serial stream ## 0.079 +- 0.4 % + Int Stepper (can par) ####= 0.186 +- 1.5 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +fast summation +10000 elements +collection.mutable.ArrayBuffer + Int, base collection # 0.043 +- 2.8 % + Int, iterator on coll # 0.038 +- 8.6 % + Int, serial stream = 0.027 +- 14.9 % + Int Stepper (can par) ## 0.083 +- 0.5 % + +fast summation +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll = 0.027 +- 5.5 % + Int, serial stream ###- 0.128 +- 0.3 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +fast summation +10000 elements +collection.mutable.ArraySeq + Int, base collection # 0.044 +- 4.0 % + Int, iterator on coll # 0.042 +- 2.9 % + Int, serial stream = 0.026 +- 15.1 % + Int Stepper (can par) #######= 0.309 +- 1.5 % + +fast summation +10000 elements +collection.mutable.ArrayStack + Int, base collection # 0.043 +- 15.3 % + Int, iterator on coll # 0.044 +- 1.8 % + Int, serial stream = 0.026 +- 11.4 % + Int Stepper (seq only) ##- 0.089 +- 0.6 % + +fast summation +10000 elements +collection.immutable.ListSet + Int, base collection #- 0.058 +- 1.8 % + Int, iterator on coll #- 0.059 +- 2.7 % + Int, serial stream = 0.022 +- 2.4 % + Int Stepper (seq only) #- 0.048 +- 35.9 % + +fast summation +10000 elements +collection.immutable.HashSet + Int, base collection = 0.028 +- 1.6 % + Int, iterator on coll = 0.023 +- 1.2 % + Int, serial stream - 0.014 +- 0.9 % + Int Stepper (can par) - 0.016 +- 1.2 % + +fast summation +10000 elements +java.util.ArrayList + Int, serial stream ######- 0.252 +- 11.9 % + +fast summation +10000 elements +java.util.LinkedList + Int, serial stream ##= 0.103 +- 7.4 % + +fast summation +10000 elements +collection.mutable.LinkedHashSet + Int, base collection # 0.044 +- 12.3 % + Int, iterator on coll #- 0.047 +- 2.8 % + Int, serial stream = 0.026 +- 14.3 % + Int Stepper (seq only) #- 0.049 +- 9.0 % + +fast summation +10000 elements +collection.immutable.List + Int, base collection #- 0.053 +- 9.6 % + Int, iterator on coll #- 0.055 +- 3.4 % + Int, serial stream # 0.040 +- 1.0 % + Int Stepper (seq only) #- 0.048 +- 34.9 % + +fast summation +10000 elements +collection.mutable.HashSet + Int, base collection = 0.021 +- 8.1 % + Int, iterator on coll = 0.023 +- 5.8 % + Int, serial stream - 0.011 +- 0.8 % + Int Stepper (can par) #= 0.067 +- 14.8 % + +fast summation +10000 elements +collection.mutable.Queue + Int, base collection - 0.009 +- 1.0 % + Int, iterator on coll = 0.028 +- 4.4 % + Int, serial stream - 0.012 +- 1.3 % + Int Stepper (seq only) - 0.016 +- 1.0 % + +fast summation +10000 elements +collection.mutable.PriorityQueue + Int, base collection # 0.034 +- 29.3 % + Int, iterator on coll # 0.043 +- 1.3 % + Int, serial stream = 0.024 +- 8.8 % + Int Stepper (seq only) # 0.036 +- 0.3 % + +fast summation +10000 elements +collection.immutable.Queue + Int, base collection #- 0.056 +- 3.3 % + Int, iterator on coll #- 0.055 +- 2.0 % + Int, serial stream = 0.026 +- 1.2 % + Int Stepper (seq only) - 0.017 +- 1.1 % + +fast summation +10000 elements +collection.immutable.Stream + Int, base collection # 0.042 +- 11.4 % + Int, iterator on coll - 0.010 +- 8.4 % + Int, serial stream = 0.022 +- 2.1 % + Int Stepper (seq only) = 0.031 +- 3.1 % + +fast summation +10000 elements +collection.immutable.TreeSet + Int, base collection #- 0.048 +- 1.4 % + Int, iterator on coll = 0.032 +- 3.8 % + Int, serial stream - 0.019 +- 2.7 % + Int Stepper (seq only) = 0.030 +- 2.5 % + +fast summation +10000 elements +collection.immutable.Vector + Int, base collection # 0.039 +- 12.1 % + Int, iterator on coll # 0.041 +- 3.3 % + Int, serial stream = 0.027 +- 14.5 % + Int Stepper (can par) ###- 0.131 +- 0.8 % + +fast summation +10000 elements +collection.mutable.WrappedArray + Int, base collection # 0.035 +- 2.0 % + Int, iterator on coll = 0.028 +- 2.5 % + Int, serial stream = 0.025 +- 17.6 % + Int Stepper (can par) #- 0.050 +- 7.6 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trigonometry +10 elements +collection.mutable.ArrayBuffer + Int, base collection ########################- 0.980 +- 0.2 % + Int, iterator on coll ########################= 0.980 +- 0.2 % + Int, serial stream ########################= 0.982 +- 0.2 % + Int Stepper (can par) ######################### 0.997 +- 0.1 % + +slow trigonometry +10 elements +Array + Int, base collection ######################### 1.000 +- 0.1 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################= 0.989 +- 0.1 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.ArraySeq + Int, base collection ################ 0.645 +- 0.1 % + Int, iterator on coll ########################= 0.980 +- 0.2 % + Int, serial stream ########################= 0.984 +- 0.1 % + Int Stepper (can par) ######################### 0.998 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.ArrayStack + Int, base collection ################ 0.642 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.5 % + Int, serial stream ########################= 0.983 +- 0.2 % + Int Stepper (seq only) ######################### 0.994 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.ListSet + Int, base collection ######################= 0.910 +- 0.3 % + Int, iterator on coll ########################- 0.978 +- 0.3 % + Int, serial stream ########################= 0.980 +- 0.2 % + Int Stepper (seq only) ########################= 0.991 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.HashSet + Int, base collection ###############= 0.628 +- 0.2 % + Int, iterator on coll ########################- 0.978 +- 0.4 % + Int, serial stream ########################- 0.977 +- 0.2 % + Int Stepper (can par) ########################= 0.989 +- 0.2 % + +slow trigonometry +10 elements +java.util.ArrayList + Int, serial stream ########################= 0.985 +- 0.2 % + +slow trigonometry +10 elements +java.util.LinkedList + Int, serial stream ########################= 0.988 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.LinkedHashSet + Int, base collection #######################= 0.950 +- 0.3 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################= 0.984 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.3 % + +slow trigonometry +10 elements +collection.immutable.List + Int, base collection ########################- 0.974 +- 0.3 % + Int, iterator on coll ########################- 0.977 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.3 % + Int Stepper (seq only) ########################= 0.990 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.HashSet + Int, base collection #######################= 0.944 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.2 % + Int, serial stream ########################- 0.979 +- 0.6 % + Int Stepper (can par) ########################= 0.993 +- 0.1 % + +slow trigonometry +10 elements +collection.mutable.Queue + Int, base collection ######################= 0.909 +- 0.3 % + Int, iterator on coll ########################- 0.977 +- 0.1 % + Int, serial stream ######################## 0.962 +- 0.2 % + Int Stepper (seq only) ########################- 0.976 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.PriorityQueue + Int, base collection ########################- 0.970 +- 0.3 % + Int, iterator on coll ########################- 0.976 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.3 % + Int Stepper (seq only) ########################= 0.990 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.Queue + Int, base collection ######################## 0.956 +- 0.2 % + Int, iterator on coll ########################- 0.976 +- 0.3 % + Int, serial stream ########################- 0.978 +- 0.6 % + Int Stepper (seq only) ########################- 0.977 +- 0.2 % + +slow trigonometry +10 elements +collection.immutable.Stream + Int, base collection #######################= 0.941 +- 0.3 % + Int, iterator on coll ######################## 0.960 +- 0.3 % + Int, serial stream ########################- 0.978 +- 0.2 % + Int Stepper (seq only) ########################= 0.991 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.TreeSet + Int, base collection ###############= 0.624 +- 0.2 % + Int, iterator on coll ########################- 0.972 +- 0.2 % + Int, serial stream ########################- 0.978 +- 0.2 % + Int Stepper (seq only) ########################= 0.987 +- 0.1 % + +slow trigonometry +10 elements +collection.immutable.Vector + Int, base collection ########################- 0.975 +- 0.2 % + Int, iterator on coll ########################= 0.981 +- 0.1 % + Int, serial stream ########################= 0.984 +- 0.1 % + Int Stepper (can par) ######################### 0.997 +- 0.2 % + +slow trigonometry +10 elements +collection.mutable.WrappedArray + Int, base collection ########################- 0.974 +- 0.2 % + Int, iterator on coll ########################- 0.980 +- 0.2 % + Int, serial stream ########################= 0.985 +- 0.2 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +slow trigonometry +10000 elements +collection.mutable.ArrayBuffer + Int, base collection ########################= 0.985 +- 0.2 % + Int, iterator on coll ########################= 0.986 +- 0.8 % + Int, serial stream ########################= 0.988 +- 0.2 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +Array + Int, base collection ######################### 1.000 +- 0.2 % + Int, iterator on coll ########################= 0.987 +- 0.2 % + Int, serial stream ########################= 0.990 +- 0.1 % + Int Stepper (can par) ######################### 1.000 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.ArraySeq + Int, base collection ################## 0.725 +- 13.6 % + Int, iterator on coll ########################= 0.988 +- 0.2 % + Int, serial stream ########################= 0.987 +- 0.3 % + Int Stepper (can par) ######################### 0.995 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.ArrayStack + Int, base collection ################- 0.651 +- 0.2 % + Int, iterator on coll ########################= 0.986 +- 0.5 % + Int, serial stream ########################= 0.988 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.1 % + +slow trigonometry +10000 elements +collection.immutable.ListSet + Int, base collection ######################- 0.888 +- 0.4 % + Int, iterator on coll ########################= 0.988 +- 0.2 % + Int, serial stream ########################= 0.986 +- 0.2 % + Int Stepper (seq only) ########################= 0.992 +- 0.2 % + +slow trigonometry +10000 elements +collection.immutable.HashSet + Int, base collection ##############- 0.569 +- 0.4 % + Int, iterator on coll ########################- 0.977 +- 0.4 % + Int, serial stream ########################- 0.969 +- 0.7 % + Int Stepper (can par) ########################- 0.969 +- 0.1 % + +slow trigonometry +10000 elements +java.util.ArrayList + Int, serial stream ########################= 0.989 +- 0.1 % + +slow trigonometry +10000 elements +java.util.LinkedList + Int, serial stream ########################= 0.989 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.LinkedHashSet + Int, base collection ####################### 0.922 +- 0.3 % + Int, iterator on coll ########################= 0.991 +- 0.2 % + Int, serial stream ########################= 0.986 +- 0.2 % + Int Stepper (seq only) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +collection.immutable.List + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ########################= 0.987 +- 0.2 % + Int Stepper (seq only) ######################### 0.995 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.HashSet + Int, base collection ######################= 0.904 +- 0.3 % + Int, iterator on coll ########################- 0.979 +- 0.3 % + Int, serial stream ########################- 0.977 +- 0.3 % + Int Stepper (can par) ########################= 0.982 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.Queue + Int, base collection #######################= 0.945 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ######################## 0.960 +- 0.7 % + Int Stepper (seq only) ######################## 0.959 +- 0.2 % + +slow trigonometry +10000 elements +collection.mutable.PriorityQueue + Int, base collection ################- 0.650 +- 0.2 % + Int, iterator on coll ########################= 0.984 +- 0.4 % + Int, serial stream ########################= 0.982 +- 0.3 % + Int Stepper (seq only) ########################= 0.983 +- 0.2 % + +slow trigonometry +10000 elements +collection.immutable.Queue + Int, base collection ######################## 0.966 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.3 % + Int, serial stream ########################- 0.975 +- 1.1 % + Int Stepper (seq only) ########################= 0.982 +- 0.3 % + +slow trigonometry +10000 elements +collection.immutable.Stream + Int, base collection #######################= 0.941 +- 0.3 % + Int, iterator on coll ######################## 0.962 +- 0.4 % + Int, serial stream ########################= 0.982 +- 0.3 % + Int Stepper (seq only) ########################= 0.988 +- 0.3 % + +slow trigonometry +10000 elements +collection.immutable.TreeSet + Int, base collection ##############- 0.571 +- 0.4 % + Int, iterator on coll ########################- 0.978 +- 0.3 % + Int, serial stream ########################- 0.973 +- 0.3 % + Int Stepper (seq only) ########################- 0.972 +- 0.6 % + +slow trigonometry +10000 elements +collection.immutable.Vector + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.990 +- 0.2 % + Int, serial stream ########################= 0.988 +- 0.1 % + Int Stepper (can par) ######################### 0.996 +- 0.1 % + +slow trigonometry +10000 elements +collection.mutable.WrappedArray + Int, base collection ########################= 0.982 +- 0.2 % + Int, iterator on coll ########################= 0.989 +- 0.1 % + Int, serial stream ########################= 0.988 +- 0.1 % + Int Stepper (can par) ########################= 0.992 +- 0.2 % +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/benchmark/results/jmhbench.log b/benchmark/results/jmhbench.log new file mode 100644 index 0000000..63568d1 --- /dev/null +++ b/benchmark/results/jmhbench.log @@ -0,0 +1,1054 @@ +[info] +[info] # Run complete. Total time: 11:52:29 +[info] +[info] Benchmark Mode Cnt Score Error Units +[info] JmhBench.bench_cI_fmc_arb_0 thrpt 25 8035423.336 ± 755409.322 ops/s +[info] JmhBench.bench_cI_fmc_arb_1 thrpt 25 20747.799 ± 136.417 ops/s +[info] JmhBench.bench_cI_fmc_arr_0 thrpt 25 71925991.876 ± 147120.839 ops/s +[info] JmhBench.bench_cI_fmc_arr_1 thrpt 25 92378.767 ± 100.507 ops/s +[info] JmhBench.bench_cI_fmc_ars_0 thrpt 25 4887009.610 ± 607583.010 ops/s +[info] JmhBench.bench_cI_fmc_ars_1 thrpt 25 16764.023 ± 542.731 ops/s +[info] JmhBench.bench_cI_fmc_ast_0 thrpt 25 5855354.579 ± 297609.045 ops/s +[info] JmhBench.bench_cI_fmc_ast_1 thrpt 25 17296.740 ± 230.641 ops/s +[info] JmhBench.bench_cI_fmc_ils_0 thrpt 25 2652720.262 ± 414787.126 ops/s +[info] JmhBench.bench_cI_fmc_ils_1 thrpt 25 487.348 ± 25.292 ops/s +[info] JmhBench.bench_cI_fmc_ish_0 thrpt 25 4987836.424 ± 646222.972 ops/s +[info] JmhBench.bench_cI_fmc_ish_1 thrpt 25 3382.659 ± 305.098 ops/s +[info] JmhBench.bench_cI_fmc_lhs_0 thrpt 25 5835320.671 ± 1009998.646 ops/s +[info] JmhBench.bench_cI_fmc_lhs_1 thrpt 25 7535.361 ± 327.683 ops/s +[info] JmhBench.bench_cI_fmc_lst_0 thrpt 25 7099167.181 ± 429761.270 ops/s +[info] JmhBench.bench_cI_fmc_lst_1 thrpt 25 12440.006 ± 224.875 ops/s +[info] JmhBench.bench_cI_fmc_mhs_0 thrpt 25 4291393.195 ± 47473.930 ops/s +[info] JmhBench.bench_cI_fmc_mhs_1 thrpt 25 4203.392 ± 112.937 ops/s +[info] JmhBench.bench_cI_fmc_muq_0 thrpt 25 2496111.379 ± 333932.718 ops/s +[info] JmhBench.bench_cI_fmc_muq_1 thrpt 25 5458.980 ± 58.848 ops/s +[info] JmhBench.bench_cI_fmc_prq_0 thrpt 25 6648768.148 ± 240161.420 ops/s +[info] JmhBench.bench_cI_fmc_prq_1 thrpt 25 9518.984 ± 882.821 ops/s +[info] JmhBench.bench_cI_fmc_que_0 thrpt 25 4993970.353 ± 84787.715 ops/s +[info] JmhBench.bench_cI_fmc_que_1 thrpt 25 7301.230 ± 48.307 ops/s +[info] JmhBench.bench_cI_fmc_stm_0 thrpt 25 5372437.328 ± 295448.912 ops/s +[info] JmhBench.bench_cI_fmc_stm_1 thrpt 25 8047.781 ± 190.906 ops/s +[info] JmhBench.bench_cI_fmc_trs_0 thrpt 25 4988067.719 ± 194129.387 ops/s +[info] JmhBench.bench_cI_fmc_trs_1 thrpt 25 2085.913 ± 52.524 ops/s +[info] JmhBench.bench_cI_fmc_vec_0 thrpt 25 6669754.581 ± 192303.049 ops/s +[info] JmhBench.bench_cI_fmc_vec_1 thrpt 25 14678.526 ± 774.640 ops/s +[info] JmhBench.bench_cI_fmc_wra_0 thrpt 25 6826577.628 ± 145826.670 ops/s +[info] JmhBench.bench_cI_fmc_wra_1 thrpt 25 11525.280 ± 217.619 ops/s +[info] JmhBench.bench_cI_mdtc_arb_0 thrpt 25 4443593.338 ± 31059.496 ops/s +[info] JmhBench.bench_cI_mdtc_arb_1 thrpt 25 11797.585 ± 410.228 ops/s +[info] JmhBench.bench_cI_mdtc_arr_0 thrpt 25 103444873.867 ± 944076.540 ops/s +[info] JmhBench.bench_cI_mdtc_arr_1 thrpt 25 75842976.523 ± 549782.886 ops/s +[info] JmhBench.bench_cI_mdtc_ars_0 thrpt 25 3207470.098 ± 38695.027 ops/s +[info] JmhBench.bench_cI_mdtc_ars_1 thrpt 25 8556.621 ± 195.807 ops/s +[info] JmhBench.bench_cI_mdtc_ast_0 thrpt 25 2355394.121 ± 38473.884 ops/s +[info] JmhBench.bench_cI_mdtc_ast_1 thrpt 25 8607.394 ± 728.653 ops/s +[info] JmhBench.bench_cI_mdtc_lst_0 thrpt 25 6468557.411 ± 137487.766 ops/s +[info] JmhBench.bench_cI_mdtc_lst_1 thrpt 25 13991.072 ± 136.574 ops/s +[info] JmhBench.bench_cI_mdtc_muq_0 thrpt 25 1345227.001 ± 58882.319 ops/s +[info] JmhBench.bench_cI_mdtc_muq_1 thrpt 25 2502.709 ± 79.914 ops/s +[info] JmhBench.bench_cI_mdtc_que_0 thrpt 25 2301715.037 ± 18642.229 ops/s +[info] JmhBench.bench_cI_mdtc_que_1 thrpt 25 4201.094 ± 57.552 ops/s +[info] JmhBench.bench_cI_mdtc_stm_0 thrpt 25 1351471.957 ± 46355.839 ops/s +[info] JmhBench.bench_cI_mdtc_stm_1 thrpt 25 664904.819 ± 42603.168 ops/s +[info] JmhBench.bench_cI_mdtc_vec_0 thrpt 25 5978680.943 ± 65546.254 ops/s +[info] JmhBench.bench_cI_mdtc_vec_1 thrpt 25 15557.817 ± 309.459 ops/s +[info] JmhBench.bench_cI_mdtc_wra_0 thrpt 25 4673494.151 ± 27640.256 ops/s +[info] JmhBench.bench_cI_mdtc_wra_1 thrpt 25 9370.962 ± 826.045 ops/s +[info] JmhBench.bench_cI_sum_arb_0 thrpt 25 18335880.324 ± 860611.155 ops/s +[info] JmhBench.bench_cI_sum_arb_1 thrpt 25 18799.347 ± 521.962 ops/s +[info] JmhBench.bench_cI_sum_arr_0 thrpt 25 113429397.689 ± 246632.083 ops/s +[info] JmhBench.bench_cI_sum_arr_1 thrpt 25 433573.009 ± 405.219 ops/s +[info] JmhBench.bench_cI_sum_ars_0 thrpt 25 18914632.257 ± 65515.415 ops/s +[info] JmhBench.bench_cI_sum_ars_1 thrpt 25 18879.126 ± 757.161 ops/s +[info] JmhBench.bench_cI_sum_ast_0 thrpt 25 19140457.190 ± 777303.561 ops/s +[info] JmhBench.bench_cI_sum_ast_1 thrpt 25 18800.310 ± 2869.443 ops/s +[info] JmhBench.bench_cI_sum_ils_0 thrpt 25 12156588.727 ± 114845.877 ops/s +[info] JmhBench.bench_cI_sum_ils_1 thrpt 25 25213.376 ± 444.053 ops/s +[info] JmhBench.bench_cI_sum_ish_0 thrpt 25 16761123.678 ± 614314.543 ops/s +[info] JmhBench.bench_cI_sum_ish_1 thrpt 25 12198.185 ± 194.961 ops/s +[info] JmhBench.bench_cI_sum_lhs_0 thrpt 25 18039130.300 ± 906017.637 ops/s +[info] JmhBench.bench_cI_sum_lhs_1 thrpt 25 18922.333 ± 2320.040 ops/s +[info] JmhBench.bench_cI_sum_lst_0 thrpt 25 29817559.612 ± 58412.021 ops/s +[info] JmhBench.bench_cI_sum_lst_1 thrpt 25 22834.330 ± 2183.263 ops/s +[info] JmhBench.bench_cI_sum_mhs_0 thrpt 25 12329436.432 ± 253623.619 ops/s +[info] JmhBench.bench_cI_sum_mhs_1 thrpt 25 8952.772 ± 723.365 ops/s +[info] JmhBench.bench_cI_sum_muq_0 thrpt 25 4613996.286 ± 35553.633 ops/s +[info] JmhBench.bench_cI_sum_muq_1 thrpt 25 3965.004 ± 40.291 ops/s +[info] JmhBench.bench_cI_sum_prq_0 thrpt 25 11768606.036 ± 322246.512 ops/s +[info] JmhBench.bench_cI_sum_prq_1 thrpt 25 14595.293 ± 4283.029 ops/s +[info] JmhBench.bench_cI_sum_que_0 thrpt 25 12216359.219 ± 84893.062 ops/s +[info] JmhBench.bench_cI_sum_que_1 thrpt 25 24107.095 ± 790.558 ops/s +[info] JmhBench.bench_cI_sum_stm_0 thrpt 25 29645049.582 ± 59278.612 ops/s +[info] JmhBench.bench_cI_sum_stm_1 thrpt 25 18080.340 ± 2059.034 ops/s +[info] JmhBench.bench_cI_sum_trs_0 thrpt 25 18874037.032 ± 120977.755 ops/s +[info] JmhBench.bench_cI_sum_trs_1 thrpt 25 20810.794 ± 288.713 ops/s +[info] JmhBench.bench_cI_sum_vec_0 thrpt 25 11742774.808 ± 63268.375 ops/s +[info] JmhBench.bench_cI_sum_vec_1 thrpt 25 16853.876 ± 2040.181 ops/s +[info] JmhBench.bench_cI_sum_wra_0 thrpt 25 16037638.914 ± 48094.558 ops/s +[info] JmhBench.bench_cI_sum_wra_1 thrpt 25 15035.828 ± 298.395 ops/s +[info] JmhBench.bench_cI_trig_arb_0 thrpt 25 127384.023 ± 230.345 ops/s +[info] JmhBench.bench_cI_trig_arb_1 thrpt 25 127.523 ± 0.207 ops/s +[info] JmhBench.bench_cI_trig_arr_0 thrpt 25 129984.043 ± 152.548 ops/s +[info] JmhBench.bench_cI_trig_arr_1 thrpt 25 129.418 ± 0.233 ops/s +[info] JmhBench.bench_cI_trig_ars_0 thrpt 25 83843.573 ± 112.771 ops/s +[info] JmhBench.bench_cI_trig_ars_1 thrpt 25 93.856 ± 12.751 ops/s +[info] JmhBench.bench_cI_trig_ast_0 thrpt 25 83514.043 ± 144.645 ops/s +[info] JmhBench.bench_cI_trig_ast_1 thrpt 25 84.199 ± 0.141 ops/s +[info] JmhBench.bench_cI_trig_ils_0 thrpt 25 118241.682 ± 333.038 ops/s +[info] JmhBench.bench_cI_trig_ils_1 thrpt 25 114.961 ± 0.485 ops/s +[info] JmhBench.bench_cI_trig_ish_0 thrpt 25 81627.106 ± 148.992 ops/s +[info] JmhBench.bench_cI_trig_ish_1 thrpt 25 73.677 ± 0.328 ops/s +[info] JmhBench.bench_cI_trig_lhs_0 thrpt 25 123484.374 ± 418.215 ops/s +[info] JmhBench.bench_cI_trig_lhs_1 thrpt 25 119.347 ± 0.338 ops/s +[info] JmhBench.bench_cI_trig_lst_0 thrpt 25 126621.643 ± 359.486 ops/s +[info] JmhBench.bench_cI_trig_lst_1 thrpt 25 127.104 ± 0.287 ops/s +[info] JmhBench.bench_cI_trig_mhs_0 thrpt 25 122733.756 ± 238.867 ops/s +[info] JmhBench.bench_cI_trig_mhs_1 thrpt 25 117.038 ± 0.317 ops/s +[info] JmhBench.bench_cI_trig_muq_0 thrpt 25 118220.195 ± 404.616 ops/s +[info] JmhBench.bench_cI_trig_muq_1 thrpt 25 122.307 ± 0.246 ops/s +[info] JmhBench.bench_cI_trig_prq_0 thrpt 25 126111.667 ± 361.165 ops/s +[info] JmhBench.bench_cI_trig_prq_1 thrpt 25 84.151 ± 0.161 ops/s +[info] JmhBench.bench_cI_trig_que_0 thrpt 25 124229.823 ± 295.406 ops/s +[info] JmhBench.bench_cI_trig_que_1 thrpt 25 124.972 ± 0.303 ops/s +[info] JmhBench.bench_cI_trig_stm_0 thrpt 25 122279.057 ± 426.484 ops/s +[info] JmhBench.bench_cI_trig_stm_1 thrpt 25 121.842 ± 0.404 ops/s +[info] JmhBench.bench_cI_trig_trs_0 thrpt 25 81105.244 ± 128.368 ops/s +[info] JmhBench.bench_cI_trig_trs_1 thrpt 25 73.845 ± 0.314 ops/s +[info] JmhBench.bench_cI_trig_vec_0 thrpt 25 126718.115 ± 223.274 ops/s +[info] JmhBench.bench_cI_trig_vec_1 thrpt 25 127.101 ± 0.219 ops/s +[info] JmhBench.bench_cI_trig_wra_0 thrpt 25 126664.936 ± 216.923 ops/s +[info] JmhBench.bench_cI_trig_wra_1 thrpt 25 127.123 ± 0.273 ops/s +[info] JmhBench.bench_cS_fmc_arb_0 thrpt 25 8309821.046 ± 49072.647 ops/s +[info] JmhBench.bench_cS_fmc_arb_1 thrpt 25 17422.556 ± 212.521 ops/s +[info] JmhBench.bench_cS_fmc_arr_0 thrpt 25 54179418.146 ± 74335.302 ops/s +[info] JmhBench.bench_cS_fmc_arr_1 thrpt 25 53181.927 ± 446.294 ops/s +[info] JmhBench.bench_cS_fmc_ars_0 thrpt 25 5103543.646 ± 215901.936 ops/s +[info] JmhBench.bench_cS_fmc_ars_1 thrpt 25 15554.519 ± 823.745 ops/s +[info] JmhBench.bench_cS_fmc_ast_0 thrpt 25 6700667.336 ± 85523.401 ops/s +[info] JmhBench.bench_cS_fmc_ast_1 thrpt 25 17258.969 ± 314.253 ops/s +[info] JmhBench.bench_cS_fmc_ils_0 thrpt 25 2941128.962 ± 142969.982 ops/s +[info] JmhBench.bench_cS_fmc_ils_1 thrpt 25 135.655 ± 11.876 ops/s +[info] JmhBench.bench_cS_fmc_ish_0 thrpt 25 5044613.272 ± 157906.830 ops/s +[info] JmhBench.bench_cS_fmc_ish_1 thrpt 25 2872.376 ± 36.541 ops/s +[info] JmhBench.bench_cS_fmc_lhs_0 thrpt 25 7265749.135 ± 101616.705 ops/s +[info] JmhBench.bench_cS_fmc_lhs_1 thrpt 25 4845.430 ± 26.025 ops/s +[info] JmhBench.bench_cS_fmc_lst_0 thrpt 25 7501407.130 ± 224844.340 ops/s +[info] JmhBench.bench_cS_fmc_lst_1 thrpt 25 9301.948 ± 312.874 ops/s +[info] JmhBench.bench_cS_fmc_mhs_0 thrpt 25 5517297.556 ± 113251.344 ops/s +[info] JmhBench.bench_cS_fmc_mhs_1 thrpt 25 2515.193 ± 13.965 ops/s +[info] JmhBench.bench_cS_fmc_muq_0 thrpt 25 1899649.245 ± 35990.877 ops/s +[info] JmhBench.bench_cS_fmc_muq_1 thrpt 25 2421.534 ± 17.772 ops/s +[info] JmhBench.bench_cS_fmc_prq_0 thrpt 25 6326339.430 ± 63789.733 ops/s +[info] JmhBench.bench_cS_fmc_prq_1 thrpt 25 6136.747 ± 671.604 ops/s +[info] JmhBench.bench_cS_fmc_que_0 thrpt 25 5503013.635 ± 251275.430 ops/s +[info] JmhBench.bench_cS_fmc_que_1 thrpt 25 7203.193 ± 147.509 ops/s +[info] JmhBench.bench_cS_fmc_stm_0 thrpt 25 5472585.642 ± 388387.172 ops/s +[info] JmhBench.bench_cS_fmc_stm_1 thrpt 25 6386.356 ± 157.946 ops/s +[info] JmhBench.bench_cS_fmc_trs_0 thrpt 25 5265384.984 ± 84795.494 ops/s +[info] JmhBench.bench_cS_fmc_trs_1 thrpt 25 1272.612 ± 11.984 ops/s +[info] JmhBench.bench_cS_fmc_vec_0 thrpt 25 6851462.782 ± 52096.647 ops/s +[info] JmhBench.bench_cS_fmc_vec_1 thrpt 25 10994.253 ± 317.945 ops/s +[info] JmhBench.bench_cS_fmc_wra_0 thrpt 25 6661645.674 ± 74676.590 ops/s +[info] JmhBench.bench_cS_fmc_wra_1 thrpt 25 17783.760 ± 433.679 ops/s +[info] JmhBench.bench_cS_htrg_arb_0 thrpt 25 98786.541 ± 135.038 ops/s +[info] JmhBench.bench_cS_htrg_arb_1 thrpt 25 98.001 ± 0.163 ops/s +[info] JmhBench.bench_cS_htrg_arr_0 thrpt 25 100566.283 ± 111.351 ops/s +[info] JmhBench.bench_cS_htrg_arr_1 thrpt 25 99.116 ± 0.146 ops/s +[info] JmhBench.bench_cS_htrg_ars_0 thrpt 25 70824.755 ± 159.884 ops/s +[info] JmhBench.bench_cS_htrg_ars_1 thrpt 25 83.161 ± 9.309 ops/s +[info] JmhBench.bench_cS_htrg_ast_0 thrpt 25 70497.771 ± 137.953 ops/s +[info] JmhBench.bench_cS_htrg_ast_1 thrpt 25 70.669 ± 0.111 ops/s +[info] JmhBench.bench_cS_htrg_ils_0 thrpt 25 93979.601 ± 143.990 ops/s +[info] JmhBench.bench_cS_htrg_ils_1 thrpt 25 90.501 ± 0.227 ops/s +[info] JmhBench.bench_cS_htrg_ish_0 thrpt 25 69330.554 ± 108.192 ops/s +[info] JmhBench.bench_cS_htrg_ish_1 thrpt 25 62.102 ± 0.265 ops/s +[info] JmhBench.bench_cS_htrg_lhs_0 thrpt 25 96535.109 ± 339.936 ops/s +[info] JmhBench.bench_cS_htrg_lhs_1 thrpt 25 93.221 ± 0.205 ops/s +[info] JmhBench.bench_cS_htrg_lst_0 thrpt 25 99009.318 ± 190.428 ops/s +[info] JmhBench.bench_cS_htrg_lst_1 thrpt 25 97.804 ± 0.203 ops/s +[info] JmhBench.bench_cS_htrg_mhs_0 thrpt 25 96569.398 ± 329.995 ops/s +[info] JmhBench.bench_cS_htrg_mhs_1 thrpt 25 90.747 ± 0.333 ops/s +[info] JmhBench.bench_cS_htrg_muq_0 thrpt 25 93247.558 ± 334.412 ops/s +[info] JmhBench.bench_cS_htrg_muq_1 thrpt 25 94.833 ± 0.283 ops/s +[info] JmhBench.bench_cS_htrg_prq_0 thrpt 25 98817.647 ± 226.278 ops/s +[info] JmhBench.bench_cS_htrg_prq_1 thrpt 25 70.441 ± 0.178 ops/s +[info] JmhBench.bench_cS_htrg_que_0 thrpt 25 97188.745 ± 169.364 ops/s +[info] JmhBench.bench_cS_htrg_que_1 thrpt 25 96.327 ± 0.291 ops/s +[info] JmhBench.bench_cS_htrg_stm_0 thrpt 25 96162.631 ± 162.971 ops/s +[info] JmhBench.bench_cS_htrg_stm_1 thrpt 25 94.593 ± 0.183 ops/s +[info] JmhBench.bench_cS_htrg_trs_0 thrpt 25 68623.297 ± 153.165 ops/s +[info] JmhBench.bench_cS_htrg_trs_1 thrpt 25 62.935 ± 0.265 ops/s +[info] JmhBench.bench_cS_htrg_vec_0 thrpt 25 98793.504 ± 237.187 ops/s +[info] JmhBench.bench_cS_htrg_vec_1 thrpt 25 97.576 ± 0.231 ops/s +[info] JmhBench.bench_cS_htrg_wra_0 thrpt 25 98854.153 ± 239.193 ops/s +[info] JmhBench.bench_cS_htrg_wra_1 thrpt 25 97.760 ± 0.233 ops/s +[info] JmhBench.bench_cS_mdtc_arb_0 thrpt 25 1918033.395 ± 16232.747 ops/s +[info] JmhBench.bench_cS_mdtc_arb_1 thrpt 25 1617.014 ± 148.727 ops/s +[info] JmhBench.bench_cS_mdtc_arr_0 thrpt 25 3952629.619 ± 25689.408 ops/s +[info] JmhBench.bench_cS_mdtc_arr_1 thrpt 25 3402684.776 ± 284371.307 ops/s +[info] JmhBench.bench_cS_mdtc_ars_0 thrpt 25 1638242.587 ± 14473.305 ops/s +[info] JmhBench.bench_cS_mdtc_ars_1 thrpt 25 1674.373 ± 103.550 ops/s +[info] JmhBench.bench_cS_mdtc_ast_0 thrpt 25 1325591.166 ± 23723.433 ops/s +[info] JmhBench.bench_cS_mdtc_ast_1 thrpt 25 1675.501 ± 116.342 ops/s +[info] JmhBench.bench_cS_mdtc_lst_0 thrpt 25 2161734.107 ± 109210.632 ops/s +[info] JmhBench.bench_cS_mdtc_lst_1 thrpt 25 1763.655 ± 175.337 ops/s +[info] JmhBench.bench_cS_mdtc_muq_0 thrpt 25 929318.339 ± 31646.687 ops/s +[info] JmhBench.bench_cS_mdtc_muq_1 thrpt 25 1139.156 ± 90.269 ops/s +[info] JmhBench.bench_cS_mdtc_que_0 thrpt 25 1327489.572 ± 14055.324 ops/s +[info] JmhBench.bench_cS_mdtc_que_1 thrpt 25 1394.055 ± 52.289 ops/s +[info] JmhBench.bench_cS_mdtc_stm_0 thrpt 25 989690.937 ± 25041.440 ops/s +[info] JmhBench.bench_cS_mdtc_stm_1 thrpt 25 928921.110 ± 18259.866 ops/s +[info] JmhBench.bench_cS_mdtc_vec_0 thrpt 25 2021845.500 ± 133044.349 ops/s +[info] JmhBench.bench_cS_mdtc_vec_1 thrpt 25 1752.712 ± 147.928 ops/s +[info] JmhBench.bench_cS_mdtc_wra_0 thrpt 25 1864950.656 ± 83548.897 ops/s +[info] JmhBench.bench_cS_mdtc_wra_1 thrpt 25 1933.967 ± 33.820 ops/s +[info] JmhBench.bench_cS_nbr_arb_0 thrpt 25 15835328.428 ± 122519.272 ops/s +[info] JmhBench.bench_cS_nbr_arb_1 thrpt 25 16840.766 ± 148.609 ops/s +[info] JmhBench.bench_cS_nbr_arr_0 thrpt 25 47695446.412 ± 182044.808 ops/s +[info] JmhBench.bench_cS_nbr_arr_1 thrpt 25 49504.973 ± 304.514 ops/s +[info] JmhBench.bench_cS_nbr_ars_0 thrpt 25 34856004.018 ± 401233.203 ops/s +[info] JmhBench.bench_cS_nbr_ars_1 thrpt 25 41092.593 ± 281.731 ops/s +[info] JmhBench.bench_cS_nbr_ast_0 thrpt 25 34757354.930 ± 535394.356 ops/s +[info] JmhBench.bench_cS_nbr_ast_1 thrpt 25 32360.450 ± 2172.594 ops/s +[info] JmhBench.bench_cS_nbr_ils_0 thrpt 25 10446844.257 ± 42499.180 ops/s +[info] JmhBench.bench_cS_nbr_ils_1 thrpt 25 18753.206 ± 5631.309 ops/s +[info] JmhBench.bench_cS_nbr_ish_0 thrpt 25 12678676.031 ± 1433593.642 ops/s +[info] JmhBench.bench_cS_nbr_ish_1 thrpt 25 6185.141 ± 193.784 ops/s +[info] JmhBench.bench_cS_nbr_lhs_0 thrpt 25 31868157.935 ± 355816.238 ops/s +[info] JmhBench.bench_cS_nbr_lhs_1 thrpt 25 34227.377 ± 800.219 ops/s +[info] JmhBench.bench_cS_nbr_lst_0 thrpt 25 29253945.968 ± 374855.998 ops/s +[info] JmhBench.bench_cS_nbr_lst_1 thrpt 25 35282.813 ± 492.016 ops/s +[info] JmhBench.bench_cS_nbr_mhs_0 thrpt 25 21835577.282 ± 1003688.165 ops/s +[info] JmhBench.bench_cS_nbr_mhs_1 thrpt 25 6272.351 ± 12.551 ops/s +[info] JmhBench.bench_cS_nbr_muq_0 thrpt 25 4114620.171 ± 31542.905 ops/s +[info] JmhBench.bench_cS_nbr_muq_1 thrpt 25 3541.869 ± 48.004 ops/s +[info] JmhBench.bench_cS_nbr_prq_0 thrpt 25 14977117.576 ± 48707.583 ops/s +[info] JmhBench.bench_cS_nbr_prq_1 thrpt 25 16714.493 ± 5012.246 ops/s +[info] JmhBench.bench_cS_nbr_que_0 thrpt 25 11073586.828 ± 41004.373 ops/s +[info] JmhBench.bench_cS_nbr_que_1 thrpt 25 18873.971 ± 6113.197 ops/s +[info] JmhBench.bench_cS_nbr_stm_0 thrpt 25 30003437.166 ± 204518.569 ops/s +[info] JmhBench.bench_cS_nbr_stm_1 thrpt 25 14211.397 ± 688.546 ops/s +[info] JmhBench.bench_cS_nbr_trs_0 thrpt 25 16120209.876 ± 69947.418 ops/s +[info] JmhBench.bench_cS_nbr_trs_1 thrpt 25 8927.765 ± 60.115 ops/s +[info] JmhBench.bench_cS_nbr_vec_0 thrpt 25 13156985.945 ± 62188.986 ops/s +[info] JmhBench.bench_cS_nbr_vec_1 thrpt 25 20392.272 ± 3067.769 ops/s +[info] JmhBench.bench_cS_nbr_wra_0 thrpt 25 16390141.475 ± 56090.429 ops/s +[info] JmhBench.bench_cS_nbr_wra_1 thrpt 25 17489.550 ± 47.421 ops/s +[info] JmhBench.bench_cpI_pfmc_arb_0 thrpt 25 27474.789 ± 928.921 ops/s +[info] JmhBench.bench_cpI_pfmc_arb_1 thrpt 25 7441.663 ± 93.625 ops/s +[info] JmhBench.bench_cpI_pfmc_arr_0 thrpt 25 28387.894 ± 596.492 ops/s +[info] JmhBench.bench_cpI_pfmc_arr_1 thrpt 25 5064.334 ± 50.797 ops/s +[info] JmhBench.bench_cpI_pfmc_ars_0 thrpt 25 28798.766 ± 335.791 ops/s +[info] JmhBench.bench_cpI_pfmc_ars_1 thrpt 25 7437.116 ± 108.032 ops/s +[info] JmhBench.bench_cpI_pfmc_ish_0 thrpt 25 23565.704 ± 517.381 ops/s +[info] JmhBench.bench_cpI_pfmc_ish_1 thrpt 25 3360.815 ± 27.573 ops/s +[info] JmhBench.bench_cpI_pfmc_mhs_0 thrpt 25 30631.073 ± 337.113 ops/s +[info] JmhBench.bench_cpI_pfmc_mhs_1 thrpt 25 3679.460 ± 44.876 ops/s +[info] JmhBench.bench_cpI_pfmc_vec_0 thrpt 25 24037.121 ± 400.303 ops/s +[info] JmhBench.bench_cpI_pfmc_vec_1 thrpt 25 6158.006 ± 137.476 ops/s +[info] JmhBench.bench_cpI_pfmc_wra_0 thrpt 25 28461.197 ± 406.506 ops/s +[info] JmhBench.bench_cpI_pfmc_wra_1 thrpt 25 5437.056 ± 62.127 ops/s +[info] JmhBench.bench_cpI_psum_arb_0 thrpt 25 72361.424 ± 4874.360 ops/s +[info] JmhBench.bench_cpI_psum_arb_1 thrpt 25 24580.891 ± 188.592 ops/s +[info] JmhBench.bench_cpI_psum_arr_0 thrpt 25 81295.376 ± 4901.317 ops/s +[info] JmhBench.bench_cpI_psum_arr_1 thrpt 25 9877.067 ± 949.170 ops/s +[info] JmhBench.bench_cpI_psum_ars_0 thrpt 25 73484.665 ± 4937.921 ops/s +[info] JmhBench.bench_cpI_psum_ars_1 thrpt 25 24514.076 ± 192.678 ops/s +[info] JmhBench.bench_cpI_psum_ish_0 thrpt 25 59907.362 ± 3036.537 ops/s +[info] JmhBench.bench_cpI_psum_ish_1 thrpt 25 12840.071 ± 125.814 ops/s +[info] JmhBench.bench_cpI_psum_mhs_0 thrpt 25 86150.260 ± 888.758 ops/s +[info] JmhBench.bench_cpI_psum_mhs_1 thrpt 25 12432.879 ± 107.465 ops/s +[info] JmhBench.bench_cpI_psum_vec_0 thrpt 25 67410.471 ± 503.168 ops/s +[info] JmhBench.bench_cpI_psum_vec_1 thrpt 25 19689.700 ± 224.288 ops/s +[info] JmhBench.bench_cpI_psum_wra_0 thrpt 25 81936.702 ± 6116.035 ops/s +[info] JmhBench.bench_cpI_psum_wra_1 thrpt 25 12562.928 ± 602.681 ops/s +[info] JmhBench.bench_cpI_ptrig_arb_0 thrpt 25 27500.407 ± 451.591 ops/s +[info] JmhBench.bench_cpI_ptrig_arb_1 thrpt 25 636.484 ± 4.737 ops/s +[info] JmhBench.bench_cpI_ptrig_arr_0 thrpt 25 27522.840 ± 278.360 ops/s +[info] JmhBench.bench_cpI_ptrig_arr_1 thrpt 25 580.587 ± 12.258 ops/s +[info] JmhBench.bench_cpI_ptrig_ars_0 thrpt 25 27760.222 ± 383.837 ops/s +[info] JmhBench.bench_cpI_ptrig_ars_1 thrpt 25 626.056 ± 13.349 ops/s +[info] JmhBench.bench_cpI_ptrig_ish_0 thrpt 25 16795.172 ± 199.894 ops/s +[info] JmhBench.bench_cpI_ptrig_ish_1 thrpt 25 495.891 ± 11.044 ops/s +[info] JmhBench.bench_cpI_ptrig_mhs_0 thrpt 25 26673.936 ± 630.916 ops/s +[info] JmhBench.bench_cpI_ptrig_mhs_1 thrpt 25 424.598 ± 15.818 ops/s +[info] JmhBench.bench_cpI_ptrig_vec_0 thrpt 25 19853.009 ± 430.607 ops/s +[info] JmhBench.bench_cpI_ptrig_vec_1 thrpt 25 406.065 ± 6.945 ops/s +[info] JmhBench.bench_cpI_ptrig_wra_0 thrpt 25 27526.423 ± 304.224 ops/s +[info] JmhBench.bench_cpI_ptrig_wra_1 thrpt 25 590.973 ± 12.122 ops/s +[info] JmhBench.bench_cpS_pfmc_arb_0 thrpt 25 28842.541 ± 242.274 ops/s +[info] JmhBench.bench_cpS_pfmc_arb_1 thrpt 25 7437.332 ± 102.398 ops/s +[info] JmhBench.bench_cpS_pfmc_arr_0 thrpt 25 28444.328 ± 788.916 ops/s +[info] JmhBench.bench_cpS_pfmc_arr_1 thrpt 25 7480.643 ± 100.594 ops/s +[info] JmhBench.bench_cpS_pfmc_ars_0 thrpt 25 28489.525 ± 464.335 ops/s +[info] JmhBench.bench_cpS_pfmc_ars_1 thrpt 25 7509.309 ± 111.292 ops/s +[info] JmhBench.bench_cpS_pfmc_ish_0 thrpt 25 24479.975 ± 278.588 ops/s +[info] JmhBench.bench_cpS_pfmc_ish_1 thrpt 25 3249.879 ± 72.414 ops/s +[info] JmhBench.bench_cpS_pfmc_mhs_0 thrpt 25 27431.881 ± 346.329 ops/s +[info] JmhBench.bench_cpS_pfmc_mhs_1 thrpt 25 3515.211 ± 32.526 ops/s +[info] JmhBench.bench_cpS_pfmc_vec_0 thrpt 25 24390.048 ± 299.352 ops/s +[info] JmhBench.bench_cpS_pfmc_vec_1 thrpt 25 5880.720 ± 40.165 ops/s +[info] JmhBench.bench_cpS_pfmc_wra_0 thrpt 25 27932.560 ± 745.187 ops/s +[info] JmhBench.bench_cpS_pfmc_wra_1 thrpt 25 7371.214 ± 122.236 ops/s +[info] JmhBench.bench_cpS_phtrg_arb_0 thrpt 25 26302.214 ± 350.122 ops/s +[info] JmhBench.bench_cpS_phtrg_arb_1 thrpt 25 461.723 ± 9.907 ops/s +[info] JmhBench.bench_cpS_phtrg_arr_0 thrpt 25 26334.485 ± 294.864 ops/s +[info] JmhBench.bench_cpS_phtrg_arr_1 thrpt 25 471.983 ± 4.097 ops/s +[info] JmhBench.bench_cpS_phtrg_ars_0 thrpt 25 26745.117 ± 302.547 ops/s +[info] JmhBench.bench_cpS_phtrg_ars_1 thrpt 25 460.382 ± 10.151 ops/s +[info] JmhBench.bench_cpS_phtrg_ish_0 thrpt 25 16794.377 ± 217.144 ops/s +[info] JmhBench.bench_cpS_phtrg_ish_1 thrpt 25 381.766 ± 7.441 ops/s +[info] JmhBench.bench_cpS_phtrg_mhs_0 thrpt 25 24664.868 ± 234.874 ops/s +[info] JmhBench.bench_cpS_phtrg_mhs_1 thrpt 25 346.646 ± 6.224 ops/s +[info] JmhBench.bench_cpS_phtrg_vec_0 thrpt 25 19515.505 ± 291.700 ops/s +[info] JmhBench.bench_cpS_phtrg_vec_1 thrpt 25 329.508 ± 4.446 ops/s +[info] JmhBench.bench_cpS_phtrg_wra_0 thrpt 25 26324.009 ± 260.212 ops/s +[info] JmhBench.bench_cpS_phtrg_wra_1 thrpt 25 457.488 ± 11.205 ops/s +[info] JmhBench.bench_cpS_pnbr_arb_0 thrpt 25 73769.996 ± 4888.976 ops/s +[info] JmhBench.bench_cpS_pnbr_arb_1 thrpt 25 26655.950 ± 267.853 ops/s +[info] JmhBench.bench_cpS_pnbr_arr_0 thrpt 25 71213.033 ± 4539.260 ops/s +[info] JmhBench.bench_cpS_pnbr_arr_1 thrpt 25 26608.171 ± 238.450 ops/s +[info] JmhBench.bench_cpS_pnbr_ars_0 thrpt 25 78247.370 ± 9646.793 ops/s +[info] JmhBench.bench_cpS_pnbr_ars_1 thrpt 25 26383.234 ± 418.183 ops/s +[info] JmhBench.bench_cpS_pnbr_ish_0 thrpt 25 72540.054 ± 2073.362 ops/s +[info] JmhBench.bench_cpS_pnbr_ish_1 thrpt 25 10859.745 ± 100.505 ops/s +[info] JmhBench.bench_cpS_pnbr_mhs_0 thrpt 25 77753.110 ± 2422.987 ops/s +[info] JmhBench.bench_cpS_pnbr_mhs_1 thrpt 25 10940.002 ± 87.312 ops/s +[info] JmhBench.bench_cpS_pnbr_vec_0 thrpt 25 64658.143 ± 2006.249 ops/s +[info] JmhBench.bench_cpS_pnbr_vec_1 thrpt 25 20204.269 ± 242.223 ops/s +[info] JmhBench.bench_cpS_pnbr_wra_0 thrpt 25 73522.170 ± 7333.002 ops/s +[info] JmhBench.bench_cpS_pnbr_wra_1 thrpt 25 26573.617 ± 275.909 ops/s +[info] JmhBench.bench_iI_fmc_arb_0 thrpt 25 11534951.751 ± 1691165.189 ops/s +[info] JmhBench.bench_iI_fmc_arb_1 thrpt 25 23810.169 ± 96.643 ops/s +[info] JmhBench.bench_iI_fmc_arr_0 thrpt 25 10757732.243 ± 1081713.666 ops/s +[info] JmhBench.bench_iI_fmc_arr_1 thrpt 25 15286.908 ± 436.672 ops/s +[info] JmhBench.bench_iI_fmc_ars_0 thrpt 25 14166687.269 ± 1566994.869 ops/s +[info] JmhBench.bench_iI_fmc_ars_1 thrpt 25 23799.914 ± 175.777 ops/s +[info] JmhBench.bench_iI_fmc_ast_0 thrpt 25 12292010.377 ± 176433.123 ops/s +[info] JmhBench.bench_iI_fmc_ast_1 thrpt 25 25241.034 ± 120.206 ops/s +[info] JmhBench.bench_iI_fmc_ils_0 thrpt 25 13282888.820 ± 1987503.472 ops/s +[info] JmhBench.bench_iI_fmc_ils_1 thrpt 25 19804.166 ± 254.272 ops/s +[info] JmhBench.bench_iI_fmc_ish_0 thrpt 25 9527444.984 ± 1365718.073 ops/s +[info] JmhBench.bench_iI_fmc_ish_1 thrpt 25 9854.394 ± 63.613 ops/s +[info] JmhBench.bench_iI_fmc_lhs_0 thrpt 25 13602398.626 ± 83211.972 ops/s +[info] JmhBench.bench_iI_fmc_lhs_1 thrpt 25 24091.137 ± 702.120 ops/s +[info] JmhBench.bench_iI_fmc_lst_0 thrpt 25 11879620.676 ± 2484773.765 ops/s +[info] JmhBench.bench_iI_fmc_lst_1 thrpt 25 19869.918 ± 309.872 ops/s +[info] JmhBench.bench_iI_fmc_mhs_0 thrpt 25 7592696.142 ± 89270.023 ops/s +[info] JmhBench.bench_iI_fmc_mhs_1 thrpt 25 10258.397 ± 167.902 ops/s +[info] JmhBench.bench_iI_fmc_muq_0 thrpt 25 7592332.150 ± 62151.207 ops/s +[info] JmhBench.bench_iI_fmc_muq_1 thrpt 25 18870.776 ± 230.705 ops/s +[info] JmhBench.bench_iI_fmc_prq_0 thrpt 25 12541183.516 ± 1500910.168 ops/s +[info] JmhBench.bench_iI_fmc_prq_1 thrpt 25 22868.330 ± 128.832 ops/s +[info] JmhBench.bench_iI_fmc_que_0 thrpt 25 8906589.116 ± 1870066.573 ops/s +[info] JmhBench.bench_iI_fmc_que_1 thrpt 25 19476.309 ± 495.972 ops/s +[info] JmhBench.bench_iI_fmc_stm_0 thrpt 25 4046667.237 ± 192062.337 ops/s +[info] JmhBench.bench_iI_fmc_stm_1 thrpt 25 4574.786 ± 302.886 ops/s +[info] JmhBench.bench_iI_fmc_trs_0 thrpt 25 8992324.317 ± 318613.523 ops/s +[info] JmhBench.bench_iI_fmc_trs_1 thrpt 25 13485.785 ± 211.286 ops/s +[info] JmhBench.bench_iI_fmc_vec_0 thrpt 25 11822416.084 ± 142156.960 ops/s +[info] JmhBench.bench_iI_fmc_vec_1 thrpt 25 19049.985 ± 180.215 ops/s +[info] JmhBench.bench_iI_fmc_wra_0 thrpt 25 9234532.837 ± 56329.639 ops/s +[info] JmhBench.bench_iI_fmc_wra_1 thrpt 25 14532.597 ± 495.601 ops/s +[info] JmhBench.bench_iI_mdtc_arb_0 thrpt 25 24564626.307 ± 3669838.680 ops/s +[info] JmhBench.bench_iI_mdtc_arb_1 thrpt 25 5108174.772 ± 678000.865 ops/s +[info] JmhBench.bench_iI_mdtc_arr_0 thrpt 25 26535121.610 ± 6675643.142 ops/s +[info] JmhBench.bench_iI_mdtc_arr_1 thrpt 25 6362301.204 ± 667303.594 ops/s +[info] JmhBench.bench_iI_mdtc_ars_0 thrpt 25 22085306.151 ± 4620817.939 ops/s +[info] JmhBench.bench_iI_mdtc_ars_1 thrpt 25 4685615.766 ± 17669.801 ops/s +[info] JmhBench.bench_iI_mdtc_ast_0 thrpt 25 26824525.002 ± 4209095.277 ops/s +[info] JmhBench.bench_iI_mdtc_ast_1 thrpt 25 6032697.890 ± 1056453.803 ops/s +[info] JmhBench.bench_iI_mdtc_lst_0 thrpt 25 27610068.280 ± 622136.640 ops/s +[info] JmhBench.bench_iI_mdtc_lst_1 thrpt 25 5461025.518 ± 41410.786 ops/s +[info] JmhBench.bench_iI_mdtc_muq_0 thrpt 25 13497138.952 ± 511813.331 ops/s +[info] JmhBench.bench_iI_mdtc_muq_1 thrpt 25 4042199.341 ± 1148290.848 ops/s +[info] JmhBench.bench_iI_mdtc_que_0 thrpt 25 22956764.241 ± 3036473.817 ops/s +[info] JmhBench.bench_iI_mdtc_que_1 thrpt 25 5744120.080 ± 575906.527 ops/s +[info] JmhBench.bench_iI_mdtc_stm_0 thrpt 25 3983205.096 ± 203586.052 ops/s +[info] JmhBench.bench_iI_mdtc_stm_1 thrpt 25 1952832.766 ± 80784.271 ops/s +[info] JmhBench.bench_iI_mdtc_vec_0 thrpt 25 26238397.353 ± 559877.283 ops/s +[info] JmhBench.bench_iI_mdtc_vec_1 thrpt 25 6202379.758 ± 981088.096 ops/s +[info] JmhBench.bench_iI_mdtc_wra_0 thrpt 25 21628417.878 ± 3218213.725 ops/s +[info] JmhBench.bench_iI_mdtc_wra_1 thrpt 25 3989870.457 ± 53216.895 ops/s +[info] JmhBench.bench_iI_sum_arb_0 thrpt 25 13677150.793 ± 196430.726 ops/s +[info] JmhBench.bench_iI_sum_arb_1 thrpt 25 16594.802 ± 1428.913 ops/s +[info] JmhBench.bench_iI_sum_arr_0 thrpt 25 11018038.688 ± 253894.491 ops/s +[info] JmhBench.bench_iI_sum_arr_1 thrpt 25 11801.147 ± 650.632 ops/s +[info] JmhBench.bench_iI_sum_ars_0 thrpt 25 15848085.664 ± 367685.730 ops/s +[info] JmhBench.bench_iI_sum_ars_1 thrpt 25 18191.993 ± 519.274 ops/s +[info] JmhBench.bench_iI_sum_ast_0 thrpt 25 17845530.592 ± 404346.784 ops/s +[info] JmhBench.bench_iI_sum_ast_1 thrpt 25 19225.305 ± 353.326 ops/s +[info] JmhBench.bench_iI_sum_ils_0 thrpt 25 18507893.432 ± 244915.056 ops/s +[info] JmhBench.bench_iI_sum_ils_1 thrpt 25 25558.552 ± 679.197 ops/s +[info] JmhBench.bench_iI_sum_ish_0 thrpt 25 9720641.170 ± 76384.111 ops/s +[info] JmhBench.bench_iI_sum_ish_1 thrpt 25 9909.417 ± 115.705 ops/s +[info] JmhBench.bench_iI_sum_lhs_0 thrpt 25 17819380.379 ± 415435.915 ops/s +[info] JmhBench.bench_iI_sum_lhs_1 thrpt 25 20293.239 ± 574.528 ops/s +[info] JmhBench.bench_iI_sum_lst_0 thrpt 25 17618830.518 ± 247702.793 ops/s +[info] JmhBench.bench_iI_sum_lst_1 thrpt 25 23871.318 ± 821.518 ops/s +[info] JmhBench.bench_iI_sum_mhs_0 thrpt 25 7920199.338 ± 25073.016 ops/s +[info] JmhBench.bench_iI_sum_mhs_1 thrpt 25 9793.600 ± 565.252 ops/s +[info] JmhBench.bench_iI_sum_muq_0 thrpt 25 9990945.720 ± 31626.968 ops/s +[info] JmhBench.bench_iI_sum_muq_1 thrpt 25 12188.211 ± 537.108 ops/s +[info] JmhBench.bench_iI_sum_prq_0 thrpt 25 15093045.013 ± 316551.848 ops/s +[info] JmhBench.bench_iI_sum_prq_1 thrpt 25 18429.280 ± 240.042 ops/s +[info] JmhBench.bench_iI_sum_que_0 thrpt 25 16518172.761 ± 133367.414 ops/s +[info] JmhBench.bench_iI_sum_que_1 thrpt 25 23915.095 ± 480.386 ops/s +[info] JmhBench.bench_iI_sum_stm_0 thrpt 25 3960336.238 ± 213043.035 ops/s +[info] JmhBench.bench_iI_sum_stm_1 thrpt 25 4173.550 ± 349.392 ops/s +[info] JmhBench.bench_iI_sum_trs_0 thrpt 25 9199624.201 ± 56259.658 ops/s +[info] JmhBench.bench_iI_sum_trs_1 thrpt 25 13869.328 ± 530.911 ops/s +[info] JmhBench.bench_iI_sum_vec_0 thrpt 25 14795372.228 ± 324576.889 ops/s +[info] JmhBench.bench_iI_sum_vec_1 thrpt 25 17685.259 ± 588.780 ops/s +[info] JmhBench.bench_iI_sum_wra_0 thrpt 25 10885962.925 ± 557809.799 ops/s +[info] JmhBench.bench_iI_sum_wra_1 thrpt 25 12222.309 ± 300.230 ops/s +[info] JmhBench.bench_iI_trig_arb_0 thrpt 25 127425.280 ± 191.414 ops/s +[info] JmhBench.bench_iI_trig_arb_1 thrpt 25 127.634 ± 0.991 ops/s +[info] JmhBench.bench_iI_trig_arr_0 thrpt 25 127512.032 ± 274.842 ops/s +[info] JmhBench.bench_iI_trig_arr_1 thrpt 25 127.698 ± 0.193 ops/s +[info] JmhBench.bench_iI_trig_ars_0 thrpt 25 127436.172 ± 238.600 ops/s +[info] JmhBench.bench_iI_trig_ars_1 thrpt 25 127.869 ± 0.295 ops/s +[info] JmhBench.bench_iI_trig_ast_0 thrpt 25 127494.683 ± 602.866 ops/s +[info] JmhBench.bench_iI_trig_ast_1 thrpt 25 127.612 ± 0.632 ops/s +[info] JmhBench.bench_iI_trig_ils_0 thrpt 25 127113.022 ± 332.672 ops/s +[info] JmhBench.bench_iI_trig_ils_1 thrpt 25 127.901 ± 0.286 ops/s +[info] JmhBench.bench_iI_trig_ish_0 thrpt 25 127092.736 ± 457.161 ops/s +[info] JmhBench.bench_iI_trig_ish_1 thrpt 25 126.436 ± 0.534 ops/s +[info] JmhBench.bench_iI_trig_lhs_0 thrpt 25 127514.664 ± 231.652 ops/s +[info] JmhBench.bench_iI_trig_lhs_1 thrpt 25 128.273 ± 0.254 ops/s +[info] JmhBench.bench_iI_trig_lst_0 thrpt 25 127022.490 ± 248.515 ops/s +[info] JmhBench.bench_iI_trig_lst_1 thrpt 25 128.115 ± 0.293 ops/s +[info] JmhBench.bench_iI_trig_mhs_0 thrpt 25 127550.698 ± 198.539 ops/s +[info] JmhBench.bench_iI_trig_mhs_1 thrpt 25 126.677 ± 0.344 ops/s +[info] JmhBench.bench_iI_trig_muq_0 thrpt 25 126992.882 ± 183.521 ops/s +[info] JmhBench.bench_iI_trig_muq_1 thrpt 25 128.114 ± 0.314 ops/s +[info] JmhBench.bench_iI_trig_prq_0 thrpt 25 126839.329 ± 193.157 ops/s +[info] JmhBench.bench_iI_trig_prq_1 thrpt 25 127.293 ± 0.463 ops/s +[info] JmhBench.bench_iI_trig_que_0 thrpt 25 126802.756 ± 375.210 ops/s +[info] JmhBench.bench_iI_trig_que_1 thrpt 25 128.106 ± 0.397 ops/s +[info] JmhBench.bench_iI_trig_stm_0 thrpt 25 124764.329 ± 430.653 ops/s +[info] JmhBench.bench_iI_trig_stm_1 thrpt 25 124.498 ± 0.485 ops/s +[info] JmhBench.bench_iI_trig_trs_0 thrpt 25 126340.545 ± 237.574 ops/s +[info] JmhBench.bench_iI_trig_trs_1 thrpt 25 126.564 ± 0.356 ops/s +[info] JmhBench.bench_iI_trig_vec_0 thrpt 25 127474.814 ± 164.684 ops/s +[info] JmhBench.bench_iI_trig_vec_1 thrpt 25 128.064 ± 0.313 ops/s +[info] JmhBench.bench_iI_trig_wra_0 thrpt 25 127331.453 ± 261.737 ops/s +[info] JmhBench.bench_iI_trig_wra_1 thrpt 25 128.023 ± 0.172 ops/s +[info] JmhBench.bench_iS_fmc_arb_0 thrpt 25 20660242.351 ± 209369.661 ops/s +[info] JmhBench.bench_iS_fmc_arb_1 thrpt 25 27552.048 ± 172.476 ops/s +[info] JmhBench.bench_iS_fmc_arr_0 thrpt 25 21065476.479 ± 205039.828 ops/s +[info] JmhBench.bench_iS_fmc_arr_1 thrpt 25 29128.579 ± 250.629 ops/s +[info] JmhBench.bench_iS_fmc_ars_0 thrpt 25 20695026.482 ± 88802.378 ops/s +[info] JmhBench.bench_iS_fmc_ars_1 thrpt 25 27806.607 ± 178.834 ops/s +[info] JmhBench.bench_iS_fmc_ast_0 thrpt 25 25600313.157 ± 317157.005 ops/s +[info] JmhBench.bench_iS_fmc_ast_1 thrpt 25 31883.764 ± 250.718 ops/s +[info] JmhBench.bench_iS_fmc_ils_0 thrpt 25 14362194.610 ± 173685.590 ops/s +[info] JmhBench.bench_iS_fmc_ils_1 thrpt 25 27422.246 ± 475.305 ops/s +[info] JmhBench.bench_iS_fmc_ish_0 thrpt 25 11106914.870 ± 304024.165 ops/s +[info] JmhBench.bench_iS_fmc_ish_1 thrpt 25 6266.457 ± 50.467 ops/s +[info] JmhBench.bench_iS_fmc_lhs_0 thrpt 25 22715287.169 ± 149617.853 ops/s +[info] JmhBench.bench_iS_fmc_lhs_1 thrpt 25 28972.273 ± 328.804 ops/s +[info] JmhBench.bench_iS_fmc_lst_0 thrpt 25 21752765.860 ± 238227.475 ops/s +[info] JmhBench.bench_iS_fmc_lst_1 thrpt 25 27163.131 ± 560.292 ops/s +[info] JmhBench.bench_iS_fmc_mhs_0 thrpt 25 13668175.591 ± 75209.492 ops/s +[info] JmhBench.bench_iS_fmc_mhs_1 thrpt 25 5765.118 ± 29.925 ops/s +[info] JmhBench.bench_iS_fmc_muq_0 thrpt 25 9638550.537 ± 157743.693 ops/s +[info] JmhBench.bench_iS_fmc_muq_1 thrpt 25 24535.554 ± 319.728 ops/s +[info] JmhBench.bench_iS_fmc_prq_0 thrpt 25 21586397.825 ± 513866.266 ops/s +[info] JmhBench.bench_iS_fmc_prq_1 thrpt 25 20012.133 ± 438.172 ops/s +[info] JmhBench.bench_iS_fmc_que_0 thrpt 25 19349313.994 ± 291925.270 ops/s +[info] JmhBench.bench_iS_fmc_que_1 thrpt 25 27455.560 ± 249.001 ops/s +[info] JmhBench.bench_iS_fmc_stm_0 thrpt 25 3967962.807 ± 230987.833 ops/s +[info] JmhBench.bench_iS_fmc_stm_1 thrpt 25 4584.761 ± 288.495 ops/s +[info] JmhBench.bench_iS_fmc_trs_0 thrpt 25 10500586.619 ± 543350.914 ops/s +[info] JmhBench.bench_iS_fmc_trs_1 thrpt 25 7758.939 ± 260.818 ops/s +[info] JmhBench.bench_iS_fmc_vec_0 thrpt 25 16202222.266 ± 1185179.036 ops/s +[info] JmhBench.bench_iS_fmc_vec_1 thrpt 25 20328.860 ± 357.803 ops/s +[info] JmhBench.bench_iS_fmc_wra_0 thrpt 25 22170885.258 ± 82756.344 ops/s +[info] JmhBench.bench_iS_fmc_wra_1 thrpt 25 28812.002 ± 257.772 ops/s +[info] JmhBench.bench_iS_htrg_arb_0 thrpt 25 99861.730 ± 209.117 ops/s +[info] JmhBench.bench_iS_htrg_arb_1 thrpt 25 98.417 ± 0.171 ops/s +[info] JmhBench.bench_iS_htrg_arr_0 thrpt 25 99625.567 ± 163.801 ops/s +[info] JmhBench.bench_iS_htrg_arr_1 thrpt 25 98.296 ± 0.210 ops/s +[info] JmhBench.bench_iS_htrg_ars_0 thrpt 25 99879.643 ± 156.190 ops/s +[info] JmhBench.bench_iS_htrg_ars_1 thrpt 25 98.363 ± 0.183 ops/s +[info] JmhBench.bench_iS_htrg_ast_0 thrpt 25 99380.973 ± 336.195 ops/s +[info] JmhBench.bench_iS_htrg_ast_1 thrpt 25 98.387 ± 0.198 ops/s +[info] JmhBench.bench_iS_htrg_ils_0 thrpt 25 99964.680 ± 174.309 ops/s +[info] JmhBench.bench_iS_htrg_ils_1 thrpt 25 98.294 ± 0.227 ops/s +[info] JmhBench.bench_iS_htrg_ish_0 thrpt 25 99433.408 ± 247.431 ops/s +[info] JmhBench.bench_iS_htrg_ish_1 thrpt 25 97.311 ± 0.150 ops/s +[info] JmhBench.bench_iS_htrg_lhs_0 thrpt 25 99265.630 ± 291.685 ops/s +[info] JmhBench.bench_iS_htrg_lhs_1 thrpt 25 98.447 ± 0.194 ops/s +[info] JmhBench.bench_iS_htrg_lst_0 thrpt 25 99902.619 ± 186.008 ops/s +[info] JmhBench.bench_iS_htrg_lst_1 thrpt 25 98.498 ± 0.209 ops/s +[info] JmhBench.bench_iS_htrg_mhs_0 thrpt 25 99003.158 ± 187.515 ops/s +[info] JmhBench.bench_iS_htrg_mhs_1 thrpt 25 96.822 ± 0.413 ops/s +[info] JmhBench.bench_iS_htrg_muq_0 thrpt 25 100012.595 ± 276.322 ops/s +[info] JmhBench.bench_iS_htrg_muq_1 thrpt 25 98.282 ± 0.258 ops/s +[info] JmhBench.bench_iS_htrg_prq_0 thrpt 25 99909.274 ± 269.579 ops/s +[info] JmhBench.bench_iS_htrg_prq_1 thrpt 25 97.929 ± 0.434 ops/s +[info] JmhBench.bench_iS_htrg_que_0 thrpt 25 99927.315 ± 151.573 ops/s +[info] JmhBench.bench_iS_htrg_que_1 thrpt 25 98.434 ± 0.299 ops/s +[info] JmhBench.bench_iS_htrg_stm_0 thrpt 25 98035.244 ± 198.742 ops/s +[info] JmhBench.bench_iS_htrg_stm_1 thrpt 25 96.635 ± 0.265 ops/s +[info] JmhBench.bench_iS_htrg_trs_0 thrpt 25 99717.022 ± 174.509 ops/s +[info] JmhBench.bench_iS_htrg_trs_1 thrpt 25 97.415 ± 0.245 ops/s +[info] JmhBench.bench_iS_htrg_vec_0 thrpt 25 99966.597 ± 221.390 ops/s +[info] JmhBench.bench_iS_htrg_vec_1 thrpt 25 98.199 ± 0.172 ops/s +[info] JmhBench.bench_iS_htrg_wra_0 thrpt 25 99874.236 ± 179.219 ops/s +[info] JmhBench.bench_iS_htrg_wra_1 thrpt 25 98.288 ± 0.196 ops/s +[info] JmhBench.bench_iS_mdtc_arb_0 thrpt 25 2097899.982 ± 23027.980 ops/s +[info] JmhBench.bench_iS_mdtc_arb_1 thrpt 25 1887060.512 ± 26123.879 ops/s +[info] JmhBench.bench_iS_mdtc_arr_0 thrpt 25 2082275.844 ± 34790.548 ops/s +[info] JmhBench.bench_iS_mdtc_arr_1 thrpt 25 1845126.936 ± 20293.322 ops/s +[info] JmhBench.bench_iS_mdtc_ars_0 thrpt 25 2009995.771 ± 76910.203 ops/s +[info] JmhBench.bench_iS_mdtc_ars_1 thrpt 25 1870000.666 ± 40742.596 ops/s +[info] JmhBench.bench_iS_mdtc_ast_0 thrpt 25 2178819.994 ± 221518.015 ops/s +[info] JmhBench.bench_iS_mdtc_ast_1 thrpt 25 2123261.170 ± 154628.266 ops/s +[info] JmhBench.bench_iS_mdtc_lst_0 thrpt 25 2328914.058 ± 32074.037 ops/s +[info] JmhBench.bench_iS_mdtc_lst_1 thrpt 25 2041954.017 ± 42234.460 ops/s +[info] JmhBench.bench_iS_mdtc_muq_0 thrpt 25 2100724.686 ± 25639.833 ops/s +[info] JmhBench.bench_iS_mdtc_muq_1 thrpt 25 1911625.218 ± 23276.435 ops/s +[info] JmhBench.bench_iS_mdtc_que_0 thrpt 25 2329239.766 ± 30110.120 ops/s +[info] JmhBench.bench_iS_mdtc_que_1 thrpt 25 2006283.293 ± 45267.124 ops/s +[info] JmhBench.bench_iS_mdtc_stm_0 thrpt 25 1639832.628 ± 33564.535 ops/s +[info] JmhBench.bench_iS_mdtc_stm_1 thrpt 25 1559980.428 ± 58314.308 ops/s +[info] JmhBench.bench_iS_mdtc_vec_0 thrpt 25 2075815.450 ± 25831.246 ops/s +[info] JmhBench.bench_iS_mdtc_vec_1 thrpt 25 1774053.986 ± 24836.414 ops/s +[info] JmhBench.bench_iS_mdtc_wra_0 thrpt 25 2082465.430 ± 54266.074 ops/s +[info] JmhBench.bench_iS_mdtc_wra_1 thrpt 25 1852111.865 ± 40534.660 ops/s +[info] JmhBench.bench_iS_nbr_arb_0 thrpt 25 15093643.409 ± 312819.522 ops/s +[info] JmhBench.bench_iS_nbr_arb_1 thrpt 25 16536.134 ± 44.776 ops/s +[info] JmhBench.bench_iS_nbr_arr_0 thrpt 25 13681116.218 ± 2069446.439 ops/s +[info] JmhBench.bench_iS_nbr_arr_1 thrpt 25 16216.197 ± 153.748 ops/s +[info] JmhBench.bench_iS_nbr_ars_0 thrpt 25 15231820.552 ± 71198.860 ops/s +[info] JmhBench.bench_iS_nbr_ars_1 thrpt 25 16431.260 ± 58.286 ops/s +[info] JmhBench.bench_iS_nbr_ast_0 thrpt 25 16422832.425 ± 160552.096 ops/s +[info] JmhBench.bench_iS_nbr_ast_1 thrpt 25 17926.164 ± 56.371 ops/s +[info] JmhBench.bench_iS_nbr_ils_0 thrpt 25 13584445.254 ± 117216.650 ops/s +[info] JmhBench.bench_iS_nbr_ils_1 thrpt 25 16068.090 ± 2653.041 ops/s +[info] JmhBench.bench_iS_nbr_ish_0 thrpt 25 13215826.280 ± 1505586.375 ops/s +[info] JmhBench.bench_iS_nbr_ish_1 thrpt 25 6105.864 ± 59.147 ops/s +[info] JmhBench.bench_iS_nbr_lhs_0 thrpt 25 17670261.677 ± 161144.754 ops/s +[info] JmhBench.bench_iS_nbr_lhs_1 thrpt 25 20389.690 ± 2324.186 ops/s +[info] JmhBench.bench_iS_nbr_lst_0 thrpt 25 16357641.101 ± 60754.533 ops/s +[info] JmhBench.bench_iS_nbr_lst_1 thrpt 25 18433.714 ± 2057.837 ops/s +[info] JmhBench.bench_iS_nbr_mhs_0 thrpt 25 11812511.313 ± 88367.679 ops/s +[info] JmhBench.bench_iS_nbr_mhs_1 thrpt 25 5600.543 ± 17.450 ops/s +[info] JmhBench.bench_iS_nbr_muq_0 thrpt 25 11691763.921 ± 46245.840 ops/s +[info] JmhBench.bench_iS_nbr_muq_1 thrpt 25 18182.019 ± 4847.548 ops/s +[info] JmhBench.bench_iS_nbr_prq_0 thrpt 25 15349594.898 ± 76157.252 ops/s +[info] JmhBench.bench_iS_nbr_prq_1 thrpt 25 15811.057 ± 4892.669 ops/s +[info] JmhBench.bench_iS_nbr_que_0 thrpt 25 15718603.188 ± 111532.970 ops/s +[info] JmhBench.bench_iS_nbr_que_1 thrpt 25 19776.658 ± 2178.055 ops/s +[info] JmhBench.bench_iS_nbr_stm_0 thrpt 25 4132893.909 ± 194559.967 ops/s +[info] JmhBench.bench_iS_nbr_stm_1 thrpt 25 4726.500 ± 338.295 ops/s +[info] JmhBench.bench_iS_nbr_trs_0 thrpt 25 10698968.841 ± 70991.716 ops/s +[info] JmhBench.bench_iS_nbr_trs_1 thrpt 25 9598.236 ± 785.458 ops/s +[info] JmhBench.bench_iS_nbr_vec_0 thrpt 25 14664874.142 ± 77772.684 ops/s +[info] JmhBench.bench_iS_nbr_vec_1 thrpt 25 17564.678 ± 3868.762 ops/s +[info] JmhBench.bench_iS_nbr_wra_0 thrpt 25 15708895.657 ± 50767.513 ops/s +[info] JmhBench.bench_iS_nbr_wra_1 thrpt 25 16808.537 ± 132.263 ops/s +[info] JmhBench.bench_spI_pfmc_arb_0 thrpt 25 122026.458 ± 3338.778 ops/s +[info] JmhBench.bench_spI_pfmc_arb_1 thrpt 25 31955.438 ± 3265.388 ops/s +[info] JmhBench.bench_spI_pfmc_arr_0 thrpt 25 123793.942 ± 1465.776 ops/s +[info] JmhBench.bench_spI_pfmc_arr_1 thrpt 25 55926.755 ± 582.057 ops/s +[info] JmhBench.bench_spI_pfmc_ars_0 thrpt 25 123838.933 ± 2528.316 ops/s +[info] JmhBench.bench_spI_pfmc_ars_1 thrpt 25 31911.979 ± 1354.094 ops/s +[info] JmhBench.bench_spI_pfmc_ish_0 thrpt 25 101313.969 ± 1541.856 ops/s +[info] JmhBench.bench_spI_pfmc_ish_1 thrpt 25 17564.133 ± 179.150 ops/s +[info] JmhBench.bench_spI_pfmc_jix_0 thrpt 25 124602.760 ± 1339.185 ops/s +[info] JmhBench.bench_spI_pfmc_jix_1 thrpt 25 46913.983 ± 1399.403 ops/s +[info] JmhBench.bench_spI_pfmc_jln_0 thrpt 25 122034.673 ± 2914.257 ops/s +[info] JmhBench.bench_spI_pfmc_jln_1 thrpt 25 21508.984 ± 2283.637 ops/s +[info] JmhBench.bench_spI_pfmc_mhs_0 thrpt 25 149803.545 ± 3416.269 ops/s +[info] JmhBench.bench_spI_pfmc_mhs_1 thrpt 25 18125.518 ± 1343.974 ops/s +[info] JmhBench.bench_spI_pfmc_vec_0 thrpt 25 121742.883 ± 1495.545 ops/s +[info] JmhBench.bench_spI_pfmc_vec_1 thrpt 25 30318.891 ± 1097.725 ops/s +[info] JmhBench.bench_spI_pfmc_wra_0 thrpt 25 124890.583 ± 706.846 ops/s +[info] JmhBench.bench_spI_pfmc_wra_1 thrpt 25 26081.649 ± 187.747 ops/s +[info] JmhBench.bench_spI_psum_arb_0 thrpt 25 120576.423 ± 1468.003 ops/s +[info] JmhBench.bench_spI_psum_arb_1 thrpt 25 33624.042 ± 476.147 ops/s +[info] JmhBench.bench_spI_psum_arr_0 thrpt 25 119288.186 ± 1423.925 ops/s +[info] JmhBench.bench_spI_psum_arr_1 thrpt 25 67775.549 ± 3304.787 ops/s +[info] JmhBench.bench_spI_psum_ars_0 thrpt 25 119588.690 ± 1729.515 ops/s +[info] JmhBench.bench_spI_psum_ars_1 thrpt 25 36403.156 ± 302.723 ops/s +[info] JmhBench.bench_spI_psum_ish_0 thrpt 25 102179.787 ± 1467.909 ops/s +[info] JmhBench.bench_spI_psum_ish_1 thrpt 25 18745.407 ± 97.495 ops/s +[info] JmhBench.bench_spI_psum_jix_0 thrpt 25 121718.375 ± 1209.540 ops/s +[info] JmhBench.bench_spI_psum_jix_1 thrpt 25 57101.512 ± 9299.544 ops/s +[info] JmhBench.bench_spI_psum_jln_0 thrpt 25 118907.263 ± 1689.327 ops/s +[info] JmhBench.bench_spI_psum_jln_1 thrpt 25 24048.469 ± 2075.903 ops/s +[info] JmhBench.bench_spI_psum_mhs_0 thrpt 25 146367.207 ± 2070.261 ops/s +[info] JmhBench.bench_spI_psum_mhs_1 thrpt 25 17278.757 ± 65.427 ops/s +[info] JmhBench.bench_spI_psum_vec_0 thrpt 25 118634.736 ± 2482.411 ops/s +[info] JmhBench.bench_spI_psum_vec_1 thrpt 25 35514.411 ± 316.920 ops/s +[info] JmhBench.bench_spI_psum_wra_0 thrpt 25 121026.432 ± 976.185 ops/s +[info] JmhBench.bench_spI_psum_wra_1 thrpt 25 26725.301 ± 163.464 ops/s +[info] JmhBench.bench_spI_ptrig_arb_0 thrpt 25 89470.600 ± 767.024 ops/s +[info] JmhBench.bench_spI_ptrig_arb_1 thrpt 25 794.995 ± 3.720 ops/s +[info] JmhBench.bench_spI_ptrig_arr_0 thrpt 25 89645.535 ± 571.222 ops/s +[info] JmhBench.bench_spI_ptrig_arr_1 thrpt 25 804.330 ± 5.509 ops/s +[info] JmhBench.bench_spI_ptrig_ars_0 thrpt 25 89499.574 ± 825.471 ops/s +[info] JmhBench.bench_spI_ptrig_ars_1 thrpt 25 782.195 ± 20.628 ops/s +[info] JmhBench.bench_spI_ptrig_ish_0 thrpt 25 77761.399 ± 661.445 ops/s +[info] JmhBench.bench_spI_ptrig_ish_1 thrpt 25 749.151 ± 5.523 ops/s +[info] JmhBench.bench_spI_ptrig_jix_0 thrpt 25 88337.024 ± 1120.008 ops/s +[info] JmhBench.bench_spI_ptrig_jix_1 thrpt 25 801.746 ± 7.369 ops/s +[info] JmhBench.bench_spI_ptrig_jln_0 thrpt 25 87959.641 ± 364.156 ops/s +[info] JmhBench.bench_spI_ptrig_jln_1 thrpt 25 739.279 ± 4.313 ops/s +[info] JmhBench.bench_spI_ptrig_mhs_0 thrpt 25 84923.215 ± 359.009 ops/s +[info] JmhBench.bench_spI_ptrig_mhs_1 thrpt 25 776.755 ± 4.260 ops/s +[info] JmhBench.bench_spI_ptrig_vec_0 thrpt 25 87511.031 ± 774.512 ops/s +[info] JmhBench.bench_spI_ptrig_vec_1 thrpt 25 788.650 ± 9.614 ops/s +[info] JmhBench.bench_spI_ptrig_wra_0 thrpt 25 89686.421 ± 971.655 ops/s +[info] JmhBench.bench_spI_ptrig_wra_1 thrpt 25 787.302 ± 5.752 ops/s +[info] JmhBench.bench_spS_pfmc_arb_0 thrpt 25 120005.523 ± 3795.221 ops/s +[info] JmhBench.bench_spS_pfmc_arb_1 thrpt 25 39776.834 ± 2984.305 ops/s +[info] JmhBench.bench_spS_pfmc_arr_0 thrpt 25 122280.558 ± 1336.325 ops/s +[info] JmhBench.bench_spS_pfmc_arr_1 thrpt 25 45979.842 ± 477.262 ops/s +[info] JmhBench.bench_spS_pfmc_ars_0 thrpt 25 123052.552 ± 1867.415 ops/s +[info] JmhBench.bench_spS_pfmc_ars_1 thrpt 25 40875.035 ± 2405.416 ops/s +[info] JmhBench.bench_spS_pfmc_ish_0 thrpt 25 103990.927 ± 1116.911 ops/s +[info] JmhBench.bench_spS_pfmc_ish_1 thrpt 25 16612.000 ± 1061.350 ops/s +[info] JmhBench.bench_spS_pfmc_jix_0 thrpt 25 118688.056 ± 3835.042 ops/s +[info] JmhBench.bench_spS_pfmc_jix_1 thrpt 25 48450.737 ± 209.135 ops/s +[info] JmhBench.bench_spS_pfmc_jln_0 thrpt 25 115844.257 ± 3520.553 ops/s +[info] JmhBench.bench_spS_pfmc_jln_1 thrpt 25 16845.440 ± 1730.417 ops/s +[info] JmhBench.bench_spS_pfmc_mhs_0 thrpt 25 131205.292 ± 1626.360 ops/s +[info] JmhBench.bench_spS_pfmc_mhs_1 thrpt 25 18525.922 ± 1488.423 ops/s +[info] JmhBench.bench_spS_pfmc_vec_0 thrpt 25 120071.251 ± 1925.718 ops/s +[info] JmhBench.bench_spS_pfmc_vec_1 thrpt 25 43352.191 ± 472.814 ops/s +[info] JmhBench.bench_spS_pfmc_wra_0 thrpt 25 124290.660 ± 2022.406 ops/s +[info] JmhBench.bench_spS_pfmc_wra_1 thrpt 25 41701.119 ± 2265.434 ops/s +[info] JmhBench.bench_spS_phtrg_arb_0 thrpt 25 81797.538 ± 548.798 ops/s +[info] JmhBench.bench_spS_phtrg_arb_1 thrpt 25 570.817 ± 5.242 ops/s +[info] JmhBench.bench_spS_phtrg_arr_0 thrpt 25 82795.075 ± 685.318 ops/s +[info] JmhBench.bench_spS_phtrg_arr_1 thrpt 25 571.434 ± 4.941 ops/s +[info] JmhBench.bench_spS_phtrg_ars_0 thrpt 25 82077.986 ± 824.614 ops/s +[info] JmhBench.bench_spS_phtrg_ars_1 thrpt 25 573.351 ± 3.988 ops/s +[info] JmhBench.bench_spS_phtrg_ish_0 thrpt 25 75813.040 ± 434.354 ops/s +[info] JmhBench.bench_spS_phtrg_ish_1 thrpt 25 532.699 ± 2.842 ops/s +[info] JmhBench.bench_spS_phtrg_jix_0 thrpt 25 82789.954 ± 556.422 ops/s +[info] JmhBench.bench_spS_phtrg_jix_1 thrpt 25 566.457 ± 11.434 ops/s +[info] JmhBench.bench_spS_phtrg_jln_0 thrpt 25 82330.442 ± 848.242 ops/s +[info] JmhBench.bench_spS_phtrg_jln_1 thrpt 25 529.041 ± 2.995 ops/s +[info] JmhBench.bench_spS_phtrg_mhs_0 thrpt 25 77381.806 ± 381.747 ops/s +[info] JmhBench.bench_spS_phtrg_mhs_1 thrpt 25 555.069 ± 2.452 ops/s +[info] JmhBench.bench_spS_phtrg_vec_0 thrpt 25 82664.902 ± 862.091 ops/s +[info] JmhBench.bench_spS_phtrg_vec_1 thrpt 25 573.708 ± 3.414 ops/s +[info] JmhBench.bench_spS_phtrg_wra_0 thrpt 25 81739.577 ± 929.248 ops/s +[info] JmhBench.bench_spS_phtrg_wra_1 thrpt 25 572.521 ± 4.090 ops/s +[info] JmhBench.bench_spS_pnbr_arb_0 thrpt 25 125276.095 ± 1514.002 ops/s +[info] JmhBench.bench_spS_pnbr_arb_1 thrpt 25 29841.668 ± 254.424 ops/s +[info] JmhBench.bench_spS_pnbr_arr_0 thrpt 25 123884.469 ± 2242.992 ops/s +[info] JmhBench.bench_spS_pnbr_arr_1 thrpt 25 34171.150 ± 571.312 ops/s +[info] JmhBench.bench_spS_pnbr_ars_0 thrpt 25 124496.684 ± 2599.330 ops/s +[info] JmhBench.bench_spS_pnbr_ars_1 thrpt 25 34250.875 ± 2183.277 ops/s +[info] JmhBench.bench_spS_pnbr_ish_0 thrpt 25 104652.916 ± 1160.961 ops/s +[info] JmhBench.bench_spS_pnbr_ish_1 thrpt 25 17229.432 ± 109.380 ops/s +[info] JmhBench.bench_spS_pnbr_jix_0 thrpt 25 123150.422 ± 1242.209 ops/s +[info] JmhBench.bench_spS_pnbr_jix_1 thrpt 25 38114.715 ± 4984.153 ops/s +[info] JmhBench.bench_spS_pnbr_jln_0 thrpt 25 120365.993 ± 1728.280 ops/s +[info] JmhBench.bench_spS_pnbr_jln_1 thrpt 25 14622.187 ± 1880.274 ops/s +[info] JmhBench.bench_spS_pnbr_mhs_0 thrpt 25 135428.927 ± 4568.452 ops/s +[info] JmhBench.bench_spS_pnbr_mhs_1 thrpt 25 15520.900 ± 88.414 ops/s +[info] JmhBench.bench_spS_pnbr_vec_0 thrpt 25 125389.867 ± 1739.809 ops/s +[info] JmhBench.bench_spS_pnbr_vec_1 thrpt 25 32482.390 ± 250.674 ops/s +[info] JmhBench.bench_spS_pnbr_wra_0 thrpt 25 124679.925 ± 2175.996 ops/s +[info] JmhBench.bench_spS_pnbr_wra_1 thrpt 25 34420.077 ± 2410.935 ops/s +[info] JmhBench.bench_ssI_fmc_arb_0 thrpt 25 9250153.823 ± 888445.531 ops/s +[info] JmhBench.bench_ssI_fmc_arb_1 thrpt 25 9355.086 ± 742.574 ops/s +[info] JmhBench.bench_ssI_fmc_arr_0 thrpt 25 16052416.844 ± 961240.618 ops/s +[info] JmhBench.bench_ssI_fmc_arr_1 thrpt 25 76936.655 ± 1407.831 ops/s +[info] JmhBench.bench_ssI_fmc_ars_0 thrpt 25 8782587.762 ± 742059.840 ops/s +[info] JmhBench.bench_ssI_fmc_ars_1 thrpt 25 9050.227 ± 780.554 ops/s +[info] JmhBench.bench_ssI_fmc_ast_0 thrpt 25 8141416.177 ± 637829.950 ops/s +[info] JmhBench.bench_ssI_fmc_ast_1 thrpt 25 10100.534 ± 503.490 ops/s +[info] JmhBench.bench_ssI_fmc_ils_0 thrpt 25 6515951.736 ± 398883.162 ops/s +[info] JmhBench.bench_ssI_fmc_ils_1 thrpt 25 9154.419 ± 328.846 ops/s +[info] JmhBench.bench_ssI_fmc_ish_0 thrpt 25 7957383.510 ± 807469.463 ops/s +[info] JmhBench.bench_ssI_fmc_ish_1 thrpt 25 8534.034 ± 76.508 ops/s +[info] JmhBench.bench_ssI_fmc_jix_0 thrpt 25 10325320.390 ± 737830.832 ops/s +[info] JmhBench.bench_ssI_fmc_jix_1 thrpt 25 23670.508 ± 1300.536 ops/s +[info] JmhBench.bench_ssI_fmc_jln_0 thrpt 25 10147871.532 ± 321143.743 ops/s +[info] JmhBench.bench_ssI_fmc_jln_1 thrpt 25 25868.179 ± 890.519 ops/s +[info] JmhBench.bench_ssI_fmc_lhs_0 thrpt 25 8167530.225 ± 68842.632 ops/s +[info] JmhBench.bench_ssI_fmc_lhs_1 thrpt 25 10305.165 ± 649.741 ops/s +[info] JmhBench.bench_ssI_fmc_lst_0 thrpt 25 7450089.752 ± 860591.681 ops/s +[info] JmhBench.bench_ssI_fmc_lst_1 thrpt 25 5580.838 ± 89.269 ops/s +[info] JmhBench.bench_ssI_fmc_mhs_0 thrpt 25 7298703.199 ± 478617.272 ops/s +[info] JmhBench.bench_ssI_fmc_mhs_1 thrpt 25 10089.122 ± 207.164 ops/s +[info] JmhBench.bench_ssI_fmc_muq_0 thrpt 25 3306530.823 ± 240247.734 ops/s +[info] JmhBench.bench_ssI_fmc_muq_1 thrpt 25 4707.455 ± 112.368 ops/s +[info] JmhBench.bench_ssI_fmc_prq_0 thrpt 25 8466869.742 ± 656493.257 ops/s +[info] JmhBench.bench_ssI_fmc_prq_1 thrpt 25 8092.785 ± 356.931 ops/s +[info] JmhBench.bench_ssI_fmc_que_0 thrpt 25 7342169.186 ± 237418.673 ops/s +[info] JmhBench.bench_ssI_fmc_que_1 thrpt 25 10399.761 ± 166.829 ops/s +[info] JmhBench.bench_ssI_fmc_stm_0 thrpt 25 7367724.075 ± 1129148.866 ops/s +[info] JmhBench.bench_ssI_fmc_stm_1 thrpt 25 8236.488 ± 2628.423 ops/s +[info] JmhBench.bench_ssI_fmc_trs_0 thrpt 25 7780121.129 ± 108678.562 ops/s +[info] JmhBench.bench_ssI_fmc_trs_1 thrpt 25 7679.958 ± 200.984 ops/s +[info] JmhBench.bench_ssI_fmc_vec_0 thrpt 25 9118653.340 ± 247215.668 ops/s +[info] JmhBench.bench_ssI_fmc_vec_1 thrpt 25 9589.100 ± 1791.009 ops/s +[info] JmhBench.bench_ssI_fmc_wra_0 thrpt 25 9262801.298 ± 456880.630 ops/s +[info] JmhBench.bench_ssI_fmc_wra_1 thrpt 25 8448.089 ± 751.665 ops/s +[info] JmhBench.bench_ssI_mdtc_arb_0 thrpt 25 6947123.970 ± 215862.500 ops/s +[info] JmhBench.bench_ssI_mdtc_arb_1 thrpt 25 4216205.596 ± 81236.212 ops/s +[info] JmhBench.bench_ssI_mdtc_arr_0 thrpt 25 7877041.387 ± 175458.225 ops/s +[info] JmhBench.bench_ssI_mdtc_arr_1 thrpt 25 4754725.775 ± 49021.630 ops/s +[info] JmhBench.bench_ssI_mdtc_ars_0 thrpt 25 6745190.439 ± 476861.322 ops/s +[info] JmhBench.bench_ssI_mdtc_ars_1 thrpt 25 4262939.806 ± 47183.691 ops/s +[info] JmhBench.bench_ssI_mdtc_ast_0 thrpt 25 6854949.067 ± 68537.150 ops/s +[info] JmhBench.bench_ssI_mdtc_ast_1 thrpt 25 4025499.567 ± 104981.719 ops/s +[info] JmhBench.bench_ssI_mdtc_jix_0 thrpt 25 5227027.825 ± 94030.854 ops/s +[info] JmhBench.bench_ssI_mdtc_jix_1 thrpt 25 3156089.920 ± 140112.857 ops/s +[info] JmhBench.bench_ssI_mdtc_jln_0 thrpt 25 5380258.918 ± 245567.821 ops/s +[info] JmhBench.bench_ssI_mdtc_jln_1 thrpt 25 3130643.665 ± 184628.801 ops/s +[info] JmhBench.bench_ssI_mdtc_lst_0 thrpt 25 6075277.338 ± 117938.332 ops/s +[info] JmhBench.bench_ssI_mdtc_lst_1 thrpt 25 4140145.442 ± 438069.320 ops/s +[info] JmhBench.bench_ssI_mdtc_muq_0 thrpt 25 2785261.264 ± 65612.901 ops/s +[info] JmhBench.bench_ssI_mdtc_muq_1 thrpt 25 1364771.167 ± 23748.839 ops/s +[info] JmhBench.bench_ssI_mdtc_que_0 thrpt 25 5122120.176 ± 104187.267 ops/s +[info] JmhBench.bench_ssI_mdtc_que_1 thrpt 25 2820520.670 ± 33621.491 ops/s +[info] JmhBench.bench_ssI_mdtc_stm_0 thrpt 25 6030630.852 ± 162783.134 ops/s +[info] JmhBench.bench_ssI_mdtc_stm_1 thrpt 25 4232143.930 ± 34806.929 ops/s +[info] JmhBench.bench_ssI_mdtc_vec_0 thrpt 25 6841092.491 ± 167568.603 ops/s +[info] JmhBench.bench_ssI_mdtc_vec_1 thrpt 25 4182368.069 ± 164073.205 ops/s +[info] JmhBench.bench_ssI_mdtc_wra_0 thrpt 25 6514842.858 ± 82706.838 ops/s +[info] JmhBench.bench_ssI_mdtc_wra_1 thrpt 25 3742865.389 ± 25362.161 ops/s +[info] JmhBench.bench_ssI_sum_arb_0 thrpt 25 9715905.252 ± 226945.687 ops/s +[info] JmhBench.bench_ssI_sum_arb_1 thrpt 25 11672.133 ± 1735.140 ops/s +[info] JmhBench.bench_ssI_sum_arr_0 thrpt 25 24618518.546 ± 257756.997 ops/s +[info] JmhBench.bench_ssI_sum_arr_1 thrpt 25 55474.149 ± 161.288 ops/s +[info] JmhBench.bench_ssI_sum_ars_0 thrpt 25 9485950.081 ± 462558.656 ops/s +[info] JmhBench.bench_ssI_sum_ars_1 thrpt 25 11299.644 ± 1711.369 ops/s +[info] JmhBench.bench_ssI_sum_ast_0 thrpt 25 8429742.725 ± 392860.041 ops/s +[info] JmhBench.bench_ssI_sum_ast_1 thrpt 25 11110.412 ± 1268.393 ops/s +[info] JmhBench.bench_ssI_sum_ils_0 thrpt 25 15909722.568 ± 349441.040 ops/s +[info] JmhBench.bench_ssI_sum_ils_1 thrpt 25 9678.768 ± 235.065 ops/s +[info] JmhBench.bench_ssI_sum_ish_0 thrpt 25 13619341.652 ± 147547.281 ops/s +[info] JmhBench.bench_ssI_sum_ish_1 thrpt 25 6212.693 ± 56.017 ops/s +[info] JmhBench.bench_ssI_sum_jix_0 thrpt 25 26310816.947 ± 153269.402 ops/s +[info] JmhBench.bench_ssI_sum_jix_1 thrpt 25 109104.485 ± 12951.334 ops/s +[info] JmhBench.bench_ssI_sum_jln_0 thrpt 25 24230659.032 ± 130893.341 ops/s +[info] JmhBench.bench_ssI_sum_jln_1 thrpt 25 44752.456 ± 3333.934 ops/s +[info] JmhBench.bench_ssI_sum_lhs_0 thrpt 25 9055689.390 ± 262812.071 ops/s +[info] JmhBench.bench_ssI_sum_lhs_1 thrpt 25 11230.558 ± 1611.547 ops/s +[info] JmhBench.bench_ssI_sum_lst_0 thrpt 25 13729453.044 ± 327014.089 ops/s +[info] JmhBench.bench_ssI_sum_lst_1 thrpt 25 17518.869 ± 183.762 ops/s +[info] JmhBench.bench_ssI_sum_mhs_0 thrpt 25 10573254.637 ± 79889.822 ops/s +[info] JmhBench.bench_ssI_sum_mhs_1 thrpt 25 4901.874 ± 36.980 ops/s +[info] JmhBench.bench_ssI_sum_muq_0 thrpt 25 3809588.908 ± 286246.301 ops/s +[info] JmhBench.bench_ssI_sum_muq_1 thrpt 25 5193.727 ± 65.227 ops/s +[info] JmhBench.bench_ssI_sum_prq_0 thrpt 25 8280044.390 ± 169984.161 ops/s +[info] JmhBench.bench_ssI_sum_prq_1 thrpt 25 10344.875 ± 908.924 ops/s +[info] JmhBench.bench_ssI_sum_que_0 thrpt 25 9207756.772 ± 1668707.276 ops/s +[info] JmhBench.bench_ssI_sum_que_1 thrpt 25 11101.518 ± 132.127 ops/s +[info] JmhBench.bench_ssI_sum_stm_0 thrpt 25 13160208.480 ± 222285.592 ops/s +[info] JmhBench.bench_ssI_sum_stm_1 thrpt 25 9703.721 ± 199.536 ops/s +[info] JmhBench.bench_ssI_sum_trs_0 thrpt 25 11550300.294 ± 168610.279 ops/s +[info] JmhBench.bench_ssI_sum_trs_1 thrpt 25 8148.181 ± 221.631 ops/s +[info] JmhBench.bench_ssI_sum_vec_0 thrpt 25 8807366.131 ± 181526.563 ops/s +[info] JmhBench.bench_ssI_sum_vec_1 thrpt 25 11708.860 ± 1701.693 ops/s +[info] JmhBench.bench_ssI_sum_wra_0 thrpt 25 8933774.049 ± 32608.515 ops/s +[info] JmhBench.bench_ssI_sum_wra_1 thrpt 25 10768.478 ± 1900.586 ops/s +[info] JmhBench.bench_ssI_trig_arb_0 thrpt 25 127701.752 ± 300.487 ops/s +[info] JmhBench.bench_ssI_trig_arb_1 thrpt 25 127.874 ± 0.244 ops/s +[info] JmhBench.bench_ssI_trig_arr_0 thrpt 25 128529.229 ± 147.708 ops/s +[info] JmhBench.bench_ssI_trig_arr_1 thrpt 25 128.141 ± 0.184 ops/s +[info] JmhBench.bench_ssI_trig_ars_0 thrpt 25 127889.038 ± 160.223 ops/s +[info] JmhBench.bench_ssI_trig_ars_1 thrpt 25 127.690 ± 0.348 ops/s +[info] JmhBench.bench_ssI_trig_ast_0 thrpt 25 127744.419 ± 223.829 ops/s +[info] JmhBench.bench_ssI_trig_ast_1 thrpt 25 127.805 ± 0.212 ops/s +[info] JmhBench.bench_ssI_trig_ils_0 thrpt 25 127427.062 ± 250.370 ops/s +[info] JmhBench.bench_ssI_trig_ils_1 thrpt 25 127.624 ± 0.198 ops/s +[info] JmhBench.bench_ssI_trig_ish_0 thrpt 25 126980.180 ± 201.098 ops/s +[info] JmhBench.bench_ssI_trig_ish_1 thrpt 25 125.386 ± 0.839 ops/s +[info] JmhBench.bench_ssI_trig_jix_0 thrpt 25 128047.658 ± 232.857 ops/s +[info] JmhBench.bench_ssI_trig_jix_1 thrpt 25 127.976 ± 0.179 ops/s +[info] JmhBench.bench_ssI_trig_jln_0 thrpt 25 128373.708 ± 156.722 ops/s +[info] JmhBench.bench_ssI_trig_jln_1 thrpt 25 127.963 ± 0.215 ops/s +[info] JmhBench.bench_ssI_trig_lhs_0 thrpt 25 127860.927 ± 268.862 ops/s +[info] JmhBench.bench_ssI_trig_lhs_1 thrpt 25 127.581 ± 0.288 ops/s +[info] JmhBench.bench_ssI_trig_lst_0 thrpt 25 127175.254 ± 376.425 ops/s +[info] JmhBench.bench_ssI_trig_lst_1 thrpt 25 127.725 ± 0.237 ops/s +[info] JmhBench.bench_ssI_trig_mhs_0 thrpt 25 127309.073 ± 796.229 ops/s +[info] JmhBench.bench_ssI_trig_mhs_1 thrpt 25 126.488 ± 0.355 ops/s +[info] JmhBench.bench_ssI_trig_muq_0 thrpt 25 125063.545 ± 299.759 ops/s +[info] JmhBench.bench_ssI_trig_muq_1 thrpt 25 124.286 ± 0.881 ops/s +[info] JmhBench.bench_ssI_trig_prq_0 thrpt 25 127111.698 ± 354.458 ops/s +[info] JmhBench.bench_ssI_trig_prq_1 thrpt 25 127.102 ± 0.424 ops/s +[info] JmhBench.bench_ssI_trig_que_0 thrpt 25 127059.599 ± 786.206 ops/s +[info] JmhBench.bench_ssI_trig_que_1 thrpt 25 126.141 ± 1.355 ops/s +[info] JmhBench.bench_ssI_trig_stm_0 thrpt 25 127112.678 ± 241.836 ops/s +[info] JmhBench.bench_ssI_trig_stm_1 thrpt 25 127.085 ± 0.441 ops/s +[info] JmhBench.bench_ssI_trig_trs_0 thrpt 25 127168.343 ± 253.254 ops/s +[info] JmhBench.bench_ssI_trig_trs_1 thrpt 25 125.868 ± 0.414 ops/s +[info] JmhBench.bench_ssI_trig_vec_0 thrpt 25 127900.540 ± 166.834 ops/s +[info] JmhBench.bench_ssI_trig_vec_1 thrpt 25 127.803 ± 0.190 ops/s +[info] JmhBench.bench_ssI_trig_wra_0 thrpt 25 128020.166 ± 213.353 ops/s +[info] JmhBench.bench_ssI_trig_wra_1 thrpt 25 127.817 ± 0.152 ops/s +[info] JmhBench.bench_ssS_fmc_arb_0 thrpt 25 7463503.099 ± 761023.850 ops/s +[info] JmhBench.bench_ssS_fmc_arb_1 thrpt 25 22735.029 ± 216.868 ops/s +[info] JmhBench.bench_ssS_fmc_arr_0 thrpt 25 7692217.391 ± 662399.601 ops/s +[info] JmhBench.bench_ssS_fmc_arr_1 thrpt 25 23523.761 ± 3082.429 ops/s +[info] JmhBench.bench_ssS_fmc_ars_0 thrpt 25 7359939.104 ± 733550.142 ops/s +[info] JmhBench.bench_ssS_fmc_ars_1 thrpt 25 18184.014 ± 3207.106 ops/s +[info] JmhBench.bench_ssS_fmc_ast_0 thrpt 25 6777545.559 ± 711554.629 ops/s +[info] JmhBench.bench_ssS_fmc_ast_1 thrpt 25 17990.091 ± 2754.649 ops/s +[info] JmhBench.bench_ssS_fmc_ils_0 thrpt 25 5536641.969 ± 173682.607 ops/s +[info] JmhBench.bench_ssS_fmc_ils_1 thrpt 25 16297.925 ± 1948.984 ops/s +[info] JmhBench.bench_ssS_fmc_ish_0 thrpt 25 5276557.648 ± 151673.651 ops/s +[info] JmhBench.bench_ssS_fmc_ish_1 thrpt 25 5487.043 ± 26.346 ops/s +[info] JmhBench.bench_ssS_fmc_jix_0 thrpt 25 8622948.878 ± 545772.382 ops/s +[info] JmhBench.bench_ssS_fmc_jix_1 thrpt 25 25400.994 ± 2093.185 ops/s +[info] JmhBench.bench_ssS_fmc_jln_0 thrpt 25 8110492.748 ± 334080.983 ops/s +[info] JmhBench.bench_ssS_fmc_jln_1 thrpt 25 26365.259 ± 2299.475 ops/s +[info] JmhBench.bench_ssS_fmc_lhs_0 thrpt 25 6786461.725 ± 739728.565 ops/s +[info] JmhBench.bench_ssS_fmc_lhs_1 thrpt 25 20871.320 ± 2145.218 ops/s +[info] JmhBench.bench_ssS_fmc_lst_0 thrpt 25 5694810.309 ± 980249.336 ops/s +[info] JmhBench.bench_ssS_fmc_lst_1 thrpt 25 16006.665 ± 115.192 ops/s +[info] JmhBench.bench_ssS_fmc_mhs_0 thrpt 25 4918958.662 ± 1011742.955 ops/s +[info] JmhBench.bench_ssS_fmc_mhs_1 thrpt 25 6243.466 ± 16.259 ops/s +[info] JmhBench.bench_ssS_fmc_muq_0 thrpt 25 3143846.099 ± 161160.702 ops/s +[info] JmhBench.bench_ssS_fmc_muq_1 thrpt 25 5153.514 ± 88.295 ops/s +[info] JmhBench.bench_ssS_fmc_prq_0 thrpt 25 6494916.233 ± 659140.032 ops/s +[info] JmhBench.bench_ssS_fmc_prq_1 thrpt 25 13046.181 ± 129.301 ops/s +[info] JmhBench.bench_ssS_fmc_que_0 thrpt 25 5233751.510 ± 600136.627 ops/s +[info] JmhBench.bench_ssS_fmc_que_1 thrpt 25 11701.632 ± 255.248 ops/s +[info] JmhBench.bench_ssS_fmc_stm_0 thrpt 25 5954886.043 ± 721275.435 ops/s +[info] JmhBench.bench_ssS_fmc_stm_1 thrpt 25 12476.953 ± 657.314 ops/s +[info] JmhBench.bench_ssS_fmc_trs_0 thrpt 25 5512418.318 ± 431220.677 ops/s +[info] JmhBench.bench_ssS_fmc_trs_1 thrpt 25 7876.367 ± 49.840 ops/s +[info] JmhBench.bench_ssS_fmc_vec_0 thrpt 25 6647652.124 ± 808794.052 ops/s +[info] JmhBench.bench_ssS_fmc_vec_1 thrpt 25 18797.521 ± 4612.928 ops/s +[info] JmhBench.bench_ssS_fmc_wra_0 thrpt 25 7312179.994 ± 727113.651 ops/s +[info] JmhBench.bench_ssS_fmc_wra_1 thrpt 25 19996.576 ± 3747.471 ops/s +[info] JmhBench.bench_ssS_htrg_arb_0 thrpt 25 99446.779 ± 280.765 ops/s +[info] JmhBench.bench_ssS_htrg_arb_1 thrpt 25 98.641 ± 0.151 ops/s +[info] JmhBench.bench_ssS_htrg_arr_0 thrpt 25 99590.833 ± 277.204 ops/s +[info] JmhBench.bench_ssS_htrg_arr_1 thrpt 25 98.728 ± 0.115 ops/s +[info] JmhBench.bench_ssS_htrg_ars_0 thrpt 25 99488.987 ± 325.960 ops/s +[info] JmhBench.bench_ssS_htrg_ars_1 thrpt 25 98.556 ± 0.157 ops/s +[info] JmhBench.bench_ssS_htrg_ast_0 thrpt 25 99404.624 ± 239.178 ops/s +[info] JmhBench.bench_ssS_htrg_ast_1 thrpt 25 98.474 ± 0.236 ops/s +[info] JmhBench.bench_ssS_htrg_ils_0 thrpt 25 99089.876 ± 928.141 ops/s +[info] JmhBench.bench_ssS_htrg_ils_1 thrpt 25 98.270 ± 0.161 ops/s +[info] JmhBench.bench_ssS_htrg_ish_0 thrpt 25 99700.720 ± 151.216 ops/s +[info] JmhBench.bench_ssS_htrg_ish_1 thrpt 25 96.097 ± 0.123 ops/s +[info] JmhBench.bench_ssS_htrg_jix_0 thrpt 25 100076.554 ± 253.018 ops/s +[info] JmhBench.bench_ssS_htrg_jix_1 thrpt 25 98.762 ± 0.134 ops/s +[info] JmhBench.bench_ssS_htrg_jln_0 thrpt 25 100312.125 ± 185.924 ops/s +[info] JmhBench.bench_ssS_htrg_jln_1 thrpt 25 98.734 ± 0.126 ops/s +[info] JmhBench.bench_ssS_htrg_lhs_0 thrpt 25 99754.119 ± 217.214 ops/s +[info] JmhBench.bench_ssS_htrg_lhs_1 thrpt 25 98.602 ± 0.120 ops/s +[info] JmhBench.bench_ssS_htrg_lst_0 thrpt 25 99829.970 ± 238.825 ops/s +[info] JmhBench.bench_ssS_htrg_lst_1 thrpt 25 98.721 ± 0.082 ops/s +[info] JmhBench.bench_ssS_htrg_mhs_0 thrpt 25 99476.088 ± 201.311 ops/s +[info] JmhBench.bench_ssS_htrg_mhs_1 thrpt 25 97.000 ± 0.127 ops/s +[info] JmhBench.bench_ssS_htrg_muq_0 thrpt 25 97745.699 ± 289.134 ops/s +[info] JmhBench.bench_ssS_htrg_muq_1 thrpt 25 96.814 ± 0.216 ops/s +[info] JmhBench.bench_ssS_htrg_prq_0 thrpt 25 99471.700 ± 420.144 ops/s +[info] JmhBench.bench_ssS_htrg_prq_1 thrpt 25 97.984 ± 0.144 ops/s +[info] JmhBench.bench_ssS_htrg_que_0 thrpt 25 99167.531 ± 519.919 ops/s +[info] JmhBench.bench_ssS_htrg_que_1 thrpt 25 97.867 ± 0.734 ops/s +[info] JmhBench.bench_ssS_htrg_stm_0 thrpt 25 99286.997 ± 493.065 ops/s +[info] JmhBench.bench_ssS_htrg_stm_1 thrpt 25 98.307 ± 0.123 ops/s +[info] JmhBench.bench_ssS_htrg_trs_0 thrpt 25 99632.863 ± 167.388 ops/s +[info] JmhBench.bench_ssS_htrg_trs_1 thrpt 25 97.235 ± 0.186 ops/s +[info] JmhBench.bench_ssS_htrg_vec_0 thrpt 25 99346.287 ± 342.790 ops/s +[info] JmhBench.bench_ssS_htrg_vec_1 thrpt 25 98.639 ± 0.134 ops/s +[info] JmhBench.bench_ssS_htrg_wra_0 thrpt 25 99393.808 ± 435.384 ops/s +[info] JmhBench.bench_ssS_htrg_wra_1 thrpt 25 98.650 ± 0.113 ops/s +[info] JmhBench.bench_ssS_mdtc_arb_0 thrpt 25 1984988.001 ± 60815.590 ops/s +[info] JmhBench.bench_ssS_mdtc_arb_1 thrpt 25 1804763.676 ± 24880.414 ops/s +[info] JmhBench.bench_ssS_mdtc_arr_0 thrpt 25 2039192.164 ± 20642.902 ops/s +[info] JmhBench.bench_ssS_mdtc_arr_1 thrpt 25 1869149.671 ± 57778.551 ops/s +[info] JmhBench.bench_ssS_mdtc_ars_0 thrpt 25 2152810.620 ± 257467.311 ops/s +[info] JmhBench.bench_ssS_mdtc_ars_1 thrpt 25 1943524.599 ± 249992.603 ops/s +[info] JmhBench.bench_ssS_mdtc_ast_0 thrpt 25 2098672.703 ± 224737.345 ops/s +[info] JmhBench.bench_ssS_mdtc_ast_1 thrpt 25 1756317.464 ± 32268.509 ops/s +[info] JmhBench.bench_ssS_mdtc_jix_0 thrpt 25 1886876.043 ± 40790.835 ops/s +[info] JmhBench.bench_ssS_mdtc_jix_1 thrpt 25 1776842.938 ± 87607.424 ops/s +[info] JmhBench.bench_ssS_mdtc_jln_0 thrpt 25 1924389.622 ± 100113.823 ops/s +[info] JmhBench.bench_ssS_mdtc_jln_1 thrpt 25 1739231.139 ± 27705.929 ops/s +[info] JmhBench.bench_ssS_mdtc_lst_0 thrpt 25 2088812.599 ± 282022.358 ops/s +[info] JmhBench.bench_ssS_mdtc_lst_1 thrpt 25 1885221.781 ± 98783.686 ops/s +[info] JmhBench.bench_ssS_mdtc_muq_0 thrpt 25 1535772.126 ± 139156.482 ops/s +[info] JmhBench.bench_ssS_mdtc_muq_1 thrpt 25 1348730.978 ± 123859.731 ops/s +[info] JmhBench.bench_ssS_mdtc_que_0 thrpt 25 1808813.567 ± 38380.283 ops/s +[info] JmhBench.bench_ssS_mdtc_que_1 thrpt 25 1859406.391 ± 243374.664 ops/s +[info] JmhBench.bench_ssS_mdtc_stm_0 thrpt 25 2159647.943 ± 261644.254 ops/s +[info] JmhBench.bench_ssS_mdtc_stm_1 thrpt 25 2060597.468 ± 239102.768 ops/s +[info] JmhBench.bench_ssS_mdtc_vec_0 thrpt 25 1960074.223 ± 19074.784 ops/s +[info] JmhBench.bench_ssS_mdtc_vec_1 thrpt 25 1838536.051 ± 83700.683 ops/s +[info] JmhBench.bench_ssS_mdtc_wra_0 thrpt 25 1974542.200 ± 19477.153 ops/s +[info] JmhBench.bench_ssS_mdtc_wra_1 thrpt 25 1846644.168 ± 61236.016 ops/s +[info] JmhBench.bench_ssS_nbr_arb_0 thrpt 25 15162942.609 ± 190397.163 ops/s +[info] JmhBench.bench_ssS_nbr_arb_1 thrpt 25 34172.246 ± 11486.810 ops/s +[info] JmhBench.bench_ssS_nbr_arr_0 thrpt 25 15507888.940 ± 238185.693 ops/s +[info] JmhBench.bench_ssS_nbr_arr_1 thrpt 25 35941.101 ± 10040.604 ops/s +[info] JmhBench.bench_ssS_nbr_ars_0 thrpt 25 15197879.786 ± 98346.084 ops/s +[info] JmhBench.bench_ssS_nbr_ars_1 thrpt 25 38301.207 ± 9362.340 ops/s +[info] JmhBench.bench_ssS_nbr_ast_0 thrpt 25 13432007.539 ± 405165.436 ops/s +[info] JmhBench.bench_ssS_nbr_ast_1 thrpt 25 32959.315 ± 8359.559 ops/s +[info] JmhBench.bench_ssS_nbr_ils_0 thrpt 25 8549875.457 ± 500035.754 ops/s +[info] JmhBench.bench_ssS_nbr_ils_1 thrpt 25 21605.083 ± 8611.146 ops/s +[info] JmhBench.bench_ssS_nbr_ish_0 thrpt 25 7664446.924 ± 98245.672 ops/s +[info] JmhBench.bench_ssS_nbr_ish_1 thrpt 25 5854.499 ± 28.620 ops/s +[info] JmhBench.bench_ssS_nbr_jix_0 thrpt 25 16089447.761 ± 68029.793 ops/s +[info] JmhBench.bench_ssS_nbr_jix_1 thrpt 25 40651.466 ± 4089.126 ops/s +[info] JmhBench.bench_ssS_nbr_jln_0 thrpt 25 14995175.785 ± 244736.253 ops/s +[info] JmhBench.bench_ssS_nbr_jln_1 thrpt 25 37382.867 ± 1452.421 ops/s +[info] JmhBench.bench_ssS_nbr_lhs_0 thrpt 25 13926273.218 ± 110410.977 ops/s +[info] JmhBench.bench_ssS_nbr_lhs_1 thrpt 25 27298.620 ± 8327.998 ops/s +[info] JmhBench.bench_ssS_nbr_lst_0 thrpt 25 10221445.868 ± 204571.661 ops/s +[info] JmhBench.bench_ssS_nbr_lst_1 thrpt 25 22706.524 ± 127.693 ops/s +[info] JmhBench.bench_ssS_nbr_mhs_0 thrpt 25 9484224.952 ± 83230.676 ops/s +[info] JmhBench.bench_ssS_nbr_mhs_1 thrpt 25 4272.497 ± 16.585 ops/s +[info] JmhBench.bench_ssS_nbr_muq_0 thrpt 25 3306298.286 ± 32629.694 ops/s +[info] JmhBench.bench_ssS_nbr_muq_1 thrpt 25 5674.616 ± 95.096 ops/s +[info] JmhBench.bench_ssS_nbr_prq_0 thrpt 25 13602518.766 ± 182996.531 ops/s +[info] JmhBench.bench_ssS_nbr_prq_1 thrpt 25 8229.425 ± 1387.909 ops/s +[info] JmhBench.bench_ssS_nbr_que_0 thrpt 25 7926786.770 ± 71210.458 ops/s +[info] JmhBench.bench_ssS_nbr_que_1 thrpt 25 12578.198 ± 340.733 ops/s +[info] JmhBench.bench_ssS_nbr_stm_0 thrpt 25 10451796.812 ± 162198.366 ops/s +[info] JmhBench.bench_ssS_nbr_stm_1 thrpt 25 10900.482 ± 876.892 ops/s +[info] JmhBench.bench_ssS_nbr_trs_0 thrpt 25 8243471.097 ± 135268.322 ops/s +[info] JmhBench.bench_ssS_nbr_trs_1 thrpt 25 5423.466 ± 46.213 ops/s +[info] JmhBench.bench_ssS_nbr_vec_0 thrpt 25 11273633.534 ± 133713.186 ops/s +[info] JmhBench.bench_ssS_nbr_vec_1 thrpt 25 22784.871 ± 3851.382 ops/s +[info] JmhBench.bench_ssS_nbr_wra_0 thrpt 25 15100257.953 ± 74244.381 ops/s +[info] JmhBench.bench_ssS_nbr_wra_1 thrpt 25 33805.074 ± 11062.118 ops/s +[info] JmhBench.bench_tpI_sum_arb_0 thrpt 25 26739900.465 ± 335390.195 ops/s +[info] JmhBench.bench_tpI_sum_arb_1 thrpt 25 36127.483 ± 192.396 ops/s +[info] JmhBench.bench_tpI_sum_arr_0 thrpt 25 96980149.604 ± 307301.990 ops/s +[info] JmhBench.bench_tpI_sum_arr_1 thrpt 25 433545.154 ± 505.319 ops/s +[info] JmhBench.bench_tpI_sum_ars_0 thrpt 25 62659319.636 ± 263473.537 ops/s +[info] JmhBench.bench_tpI_sum_ars_1 thrpt 25 134066.476 ± 2016.903 ops/s +[info] JmhBench.bench_tpI_sum_ish_0 thrpt 25 13553901.120 ± 539231.487 ops/s +[info] JmhBench.bench_tpI_sum_ish_1 thrpt 25 7114.146 ± 88.443 ops/s +[info] JmhBench.bench_tpI_sum_mhs_0 thrpt 25 34967900.851 ± 170504.872 ops/s +[info] JmhBench.bench_tpI_sum_mhs_1 thrpt 25 28972.583 ± 4297.660 ops/s +[info] JmhBench.bench_tpI_sum_vec_0 thrpt 25 40722024.527 ± 324420.816 ops/s +[info] JmhBench.bench_tpI_sum_vec_1 thrpt 25 56600.790 ± 453.750 ops/s +[info] JmhBench.bench_tpI_sum_wra_0 thrpt 25 21076023.537 ± 321478.351 ops/s +[info] JmhBench.bench_tpI_sum_wra_1 thrpt 25 21466.089 ± 1622.643 ops/s +[info] JmhBench.bench_tpI_trig_arb_0 thrpt 25 129620.815 ± 139.024 ops/s +[info] JmhBench.bench_tpI_trig_arb_1 thrpt 25 128.952 ± 0.106 ops/s +[info] JmhBench.bench_tpI_trig_arr_0 thrpt 25 129958.638 ± 148.953 ops/s +[info] JmhBench.bench_tpI_trig_arr_1 thrpt 25 129.385 ± 0.112 ops/s +[info] JmhBench.bench_tpI_trig_ars_0 thrpt 25 129745.070 ± 228.564 ops/s +[info] JmhBench.bench_tpI_trig_ars_1 thrpt 25 128.757 ± 0.199 ops/s +[info] JmhBench.bench_tpI_trig_ish_0 thrpt 25 128598.096 ± 207.794 ops/s +[info] JmhBench.bench_tpI_trig_ish_1 thrpt 25 125.427 ± 0.108 ops/s +[info] JmhBench.bench_tpI_trig_mhs_0 thrpt 25 129109.741 ± 173.754 ops/s +[info] JmhBench.bench_tpI_trig_mhs_1 thrpt 25 127.048 ± 0.209 ops/s +[info] JmhBench.bench_tpI_trig_vec_0 thrpt 25 129567.839 ± 205.096 ops/s +[info] JmhBench.bench_tpI_trig_vec_1 thrpt 25 128.955 ± 0.139 ops/s +[info] JmhBench.bench_tpI_trig_wra_0 thrpt 25 129438.595 ± 145.718 ops/s +[info] JmhBench.bench_tpI_trig_wra_1 thrpt 25 128.359 ± 0.198 ops/s +[info] JmhBench.bench_tpS_htrg_arb_0 thrpt 25 100158.018 ± 205.248 ops/s +[info] JmhBench.bench_tpS_htrg_arb_1 thrpt 25 98.649 ± 0.169 ops/s +[info] JmhBench.bench_tpS_htrg_arr_0 thrpt 25 100144.281 ± 158.463 ops/s +[info] JmhBench.bench_tpS_htrg_arr_1 thrpt 25 98.765 ± 0.260 ops/s +[info] JmhBench.bench_tpS_htrg_ars_0 thrpt 25 100096.628 ± 172.960 ops/s +[info] JmhBench.bench_tpS_htrg_ars_1 thrpt 25 98.710 ± 0.179 ops/s +[info] JmhBench.bench_tpS_htrg_ish_0 thrpt 25 99760.501 ± 217.237 ops/s +[info] JmhBench.bench_tpS_htrg_ish_1 thrpt 25 97.228 ± 0.519 ops/s +[info] JmhBench.bench_tpS_htrg_mhs_0 thrpt 25 99806.585 ± 153.342 ops/s +[info] JmhBench.bench_tpS_htrg_mhs_1 thrpt 25 97.412 ± 0.354 ops/s +[info] JmhBench.bench_tpS_htrg_vec_0 thrpt 25 99612.078 ± 530.034 ops/s +[info] JmhBench.bench_tpS_htrg_vec_1 thrpt 25 98.638 ± 0.206 ops/s +[info] JmhBench.bench_tpS_htrg_wra_0 thrpt 25 100084.080 ± 194.389 ops/s +[info] JmhBench.bench_tpS_htrg_wra_1 thrpt 25 98.759 ± 0.217 ops/s +[info] JmhBench.bench_tpS_nbr_arb_0 thrpt 25 27773552.600 ± 107286.891 ops/s +[info] JmhBench.bench_tpS_nbr_arb_1 thrpt 25 26047.916 ± 541.631 ops/s +[info] JmhBench.bench_tpS_nbr_arr_0 thrpt 25 32696587.907 ± 125809.446 ops/s +[info] JmhBench.bench_tpS_nbr_arr_1 thrpt 25 31707.576 ± 1469.663 ops/s +[info] JmhBench.bench_tpS_nbr_ars_0 thrpt 25 27763273.573 ± 75994.385 ops/s +[info] JmhBench.bench_tpS_nbr_ars_1 thrpt 25 25907.969 ± 499.582 ops/s +[info] JmhBench.bench_tpS_nbr_ish_0 thrpt 25 10561733.949 ± 333991.228 ops/s +[info] JmhBench.bench_tpS_nbr_ish_1 thrpt 25 6686.211 ± 38.894 ops/s +[info] JmhBench.bench_tpS_nbr_mhs_0 thrpt 25 20592408.675 ± 290612.904 ops/s +[info] JmhBench.bench_tpS_nbr_mhs_1 thrpt 25 6586.088 ± 57.671 ops/s +[info] JmhBench.bench_tpS_nbr_vec_0 thrpt 25 19918742.462 ± 129361.736 ops/s +[info] JmhBench.bench_tpS_nbr_vec_1 thrpt 25 22393.856 ± 660.971 ops/s +[info] JmhBench.bench_tpS_nbr_wra_0 thrpt 25 27798715.944 ± 399855.662 ops/s +[info] JmhBench.bench_tpS_nbr_wra_1 thrpt 25 26368.583 ± 698.515 ops/s +[info] JmhBench.bench_tsI_sum_ast_0 thrpt 25 29292472.271 ± 378141.088 ops/s +[info] JmhBench.bench_tsI_sum_ast_1 thrpt 25 38732.103 ± 250.264 ops/s +[info] JmhBench.bench_tsI_sum_ils_0 thrpt 25 12612812.138 ± 2285614.348 ops/s +[info] JmhBench.bench_tsI_sum_ils_1 thrpt 25 20618.454 ± 7399.667 ops/s +[info] JmhBench.bench_tsI_sum_lhs_0 thrpt 25 19047956.030 ± 102806.511 ops/s +[info] JmhBench.bench_tsI_sum_lhs_1 thrpt 25 21098.108 ± 1892.775 ops/s +[info] JmhBench.bench_tsI_sum_lst_0 thrpt 25 13250785.213 ± 284214.672 ops/s +[info] JmhBench.bench_tsI_sum_lst_1 thrpt 25 20620.823 ± 7198.647 ops/s +[info] JmhBench.bench_tsI_sum_muq_0 thrpt 25 6186108.761 ± 49405.604 ops/s +[info] JmhBench.bench_tsI_sum_muq_1 thrpt 25 6953.879 ± 68.504 ops/s +[info] JmhBench.bench_tsI_sum_prq_0 thrpt 25 15439239.952 ± 61151.281 ops/s +[info] JmhBench.bench_tsI_sum_prq_1 thrpt 25 15760.730 ± 44.485 ops/s +[info] JmhBench.bench_tsI_sum_que_0 thrpt 25 6544132.929 ± 90771.895 ops/s +[info] JmhBench.bench_tsI_sum_que_1 thrpt 25 7583.197 ± 82.784 ops/s +[info] JmhBench.bench_tsI_sum_stm_0 thrpt 25 12838212.904 ± 40317.104 ops/s +[info] JmhBench.bench_tsI_sum_stm_1 thrpt 25 13428.876 ± 412.327 ops/s +[info] JmhBench.bench_tsI_sum_trs_0 thrpt 25 11018879.369 ± 36863.225 ops/s +[info] JmhBench.bench_tsI_sum_trs_1 thrpt 25 12874.559 ± 320.397 ops/s +[info] JmhBench.bench_tsI_trig_ast_0 thrpt 25 129218.582 ± 247.185 ops/s +[info] JmhBench.bench_tsI_trig_ast_1 thrpt 25 128.730 ± 0.134 ops/s +[info] JmhBench.bench_tsI_trig_ils_0 thrpt 25 128764.813 ± 270.973 ops/s +[info] JmhBench.bench_tsI_trig_ils_1 thrpt 25 128.383 ± 0.229 ops/s +[info] JmhBench.bench_tsI_trig_lhs_0 thrpt 25 129310.531 ± 402.325 ops/s +[info] JmhBench.bench_tsI_trig_lhs_1 thrpt 25 128.862 ± 0.132 ops/s +[info] JmhBench.bench_tsI_trig_lst_0 thrpt 25 128629.859 ± 169.266 ops/s +[info] JmhBench.bench_tsI_trig_lst_1 thrpt 25 128.817 ± 0.136 ops/s +[info] JmhBench.bench_tsI_trig_muq_0 thrpt 25 126882.540 ± 261.902 ops/s +[info] JmhBench.bench_tsI_trig_muq_1 thrpt 25 124.074 ± 0.275 ops/s +[info] JmhBench.bench_tsI_trig_prq_0 thrpt 25 128704.594 ± 132.903 ops/s +[info] JmhBench.bench_tsI_trig_prq_1 thrpt 25 127.264 ± 0.215 ops/s +[info] JmhBench.bench_tsI_trig_que_0 thrpt 25 127027.541 ± 305.857 ops/s +[info] JmhBench.bench_tsI_trig_que_1 thrpt 25 127.115 ± 0.387 ops/s +[info] JmhBench.bench_tsI_trig_stm_0 thrpt 25 128763.321 ± 170.721 ops/s +[info] JmhBench.bench_tsI_trig_stm_1 thrpt 25 127.858 ± 0.341 ops/s +[info] JmhBench.bench_tsI_trig_trs_0 thrpt 25 128251.208 ± 143.219 ops/s +[info] JmhBench.bench_tsI_trig_trs_1 thrpt 25 125.752 ± 0.714 ops/s +[info] JmhBench.bench_tsS_htrg_ast_0 thrpt 25 99993.610 ± 190.884 ops/s +[info] JmhBench.bench_tsS_htrg_ast_1 thrpt 25 98.665 ± 0.229 ops/s +[info] JmhBench.bench_tsS_htrg_ils_0 thrpt 25 99769.301 ± 181.360 ops/s +[info] JmhBench.bench_tsS_htrg_ils_1 thrpt 25 97.749 ± 0.981 ops/s +[info] JmhBench.bench_tsS_htrg_lhs_0 thrpt 25 99843.502 ± 435.773 ops/s +[info] JmhBench.bench_tsS_htrg_lhs_1 thrpt 25 98.554 ± 0.370 ops/s +[info] JmhBench.bench_tsS_htrg_lst_0 thrpt 25 99994.704 ± 271.382 ops/s +[info] JmhBench.bench_tsS_htrg_lst_1 thrpt 25 98.679 ± 0.216 ops/s +[info] JmhBench.bench_tsS_htrg_muq_0 thrpt 25 97832.075 ± 224.268 ops/s +[info] JmhBench.bench_tsS_htrg_muq_1 thrpt 25 96.275 ± 0.219 ops/s +[info] JmhBench.bench_tsS_htrg_prq_0 thrpt 25 100041.101 ± 215.115 ops/s +[info] JmhBench.bench_tsS_htrg_prq_1 thrpt 25 98.142 ± 0.362 ops/s +[info] JmhBench.bench_tsS_htrg_que_0 thrpt 25 99899.045 ± 199.887 ops/s +[info] JmhBench.bench_tsS_htrg_que_1 thrpt 25 98.160 ± 0.193 ops/s +[info] JmhBench.bench_tsS_htrg_stm_0 thrpt 25 99938.866 ± 583.593 ops/s +[info] JmhBench.bench_tsS_htrg_stm_1 thrpt 25 98.389 ± 0.258 ops/s +[info] JmhBench.bench_tsS_htrg_trs_0 thrpt 25 99843.112 ± 278.174 ops/s +[info] JmhBench.bench_tsS_htrg_trs_1 thrpt 25 97.433 ± 0.404 ops/s +[info] JmhBench.bench_tsS_nbr_ast_0 thrpt 25 24754126.558 ± 2252827.519 ops/s +[info] JmhBench.bench_tsS_nbr_ast_1 thrpt 25 25470.616 ± 2313.648 ops/s +[info] JmhBench.bench_tsS_nbr_ils_0 thrpt 25 18815243.091 ± 229054.186 ops/s +[info] JmhBench.bench_tsS_nbr_ils_1 thrpt 25 18405.753 ± 1106.520 ops/s +[info] JmhBench.bench_tsS_nbr_lhs_0 thrpt 25 23611132.342 ± 214340.942 ops/s +[info] JmhBench.bench_tsS_nbr_lhs_1 thrpt 25 19916.336 ± 750.264 ops/s +[info] JmhBench.bench_tsS_nbr_lst_0 thrpt 25 16162287.601 ± 386166.719 ops/s +[info] JmhBench.bench_tsS_nbr_lst_1 thrpt 25 15050.506 ± 225.637 ops/s +[info] JmhBench.bench_tsS_nbr_muq_0 thrpt 25 3990516.577 ± 72332.103 ops/s +[info] JmhBench.bench_tsS_nbr_muq_1 thrpt 25 3957.072 ± 47.475 ops/s +[info] JmhBench.bench_tsS_nbr_prq_0 thrpt 25 24071415.301 ± 190014.780 ops/s +[info] JmhBench.bench_tsS_nbr_prq_1 thrpt 25 12006.143 ± 668.510 ops/s +[info] JmhBench.bench_tsS_nbr_que_0 thrpt 25 11035865.936 ± 125073.361 ops/s +[info] JmhBench.bench_tsS_nbr_que_1 thrpt 25 10895.451 ± 82.204 ops/s +[info] JmhBench.bench_tsS_nbr_stm_0 thrpt 25 15774294.393 ± 161310.226 ops/s +[info] JmhBench.bench_tsS_nbr_stm_1 thrpt 25 12751.885 ± 218.859 ops/s +[info] JmhBench.bench_tsS_nbr_trs_0 thrpt 25 12164073.361 ± 417198.078 ops/s +[info] JmhBench.bench_tsS_nbr_trs_1 thrpt 25 9425.149 ± 212.728 ops/s +[success] Total time: 42760 s, completed Jan 6, 2016 11:28:41 AM +> diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 7563a88..4e206ce 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -9,12 +9,13 @@ object Generator { val annotated = "arr ish! lst* ils*! que* stm* trs*! vec arb ars ast* mhs! lhs*! prq*! muq* wra jix jln".split(' ') // Parallel version if any appears after / + // Trailing % means that operation creates new collections and thus can't be used with Stepper (sequential ops only) // Trailing ! means that collection must maintain original order (i.e. don't use if collection is marked !) - val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc/pfmc mdtc!"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc/pfmc mdtc!")) + val allops = Seq(("OnInt", "I", "sum/psum trig/ptrig fmc%/pfmc mdtc!%"), ("OnString", "S", "nbr/pnbr htrg/phtrg fmc%/pfmc mdtc!%")) def parsefs(fs: String) = fs.split(' ').map(_.split('/') match { - case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!") - case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!") + case Array(x) => (x.takeWhile(_.isLetter), None, x contains "!", x contains "%") + case Array(x,y) => (x.takeWhile(_.isLetter), Some(y.takeWhile(_.isLetter)), (x+y) contains "!", x contains "%") }) val names = annotated.map(_.takeWhile(_.isLetter)) @@ -60,23 +61,29 @@ object Generator { names.foreach{ n => pr( s" { // Scope for operations $o collection $n") pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => if (ordname(n) || !ord) { pr( """ for (i <- 0 until m) {""") pr( s" val z = $o.$f(x.arr.c$t(i))") if (nojname(n)) { - pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)"); + pr( s" check(z, $o.$f(x.$n.c$t(i)), ${q}c$t $f $n ${q}+i.toString)") pr( s" check(z, $o.$f(x.$n.i$t(i)), ${q}i$t $f $n ${q}+i.toString)") + if (pf.isDefined) + pr( s" check(z, $o.${pf.get}(x.$n.c$t(i).par), ${q}i$t ${pf.get} $n ${q}+i.toString)") } - if (sqnname(n)) { + if (sqnname(n) || parname(n)) { pr( s" check(z, $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n ${q}+i.toString)") - if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zs$t(i)), ${q}zs$t $f $n ${q}+i.toString)") + if (nojname(n) && !nu) { + if (sqnname(n)) + pr( s" check(z, $o.$f(x.$n.ts$t(i)), ${q}ts$t $f $n ${q}+i.toString)") + else + pr( s" check(z, $o.$f(x.$n.tp$t(i)), ${q}tp$t $f $n ${q}+i.toString)") + } } if (parname(n) && pf.isDefined) { - pr( s" check(z, $o.$f(x.$n.sp$t(i)), ${q}sp$t $f $n ${q}+i.toString)") - if (nojname(n)) - pr( s" check(z, $o.$f(x.$n.zp$t(i)), ${q}zp$t $f $n ${q}+i.toString)") + pr( s" check(z, $o.${pf.get}(x.$n.sp$t(i)), ${q}sp$t ${pf.get} $n ${q}+i.toString)") + if (nojname(n) && !nu) + pr( s" check(z, $o.${pf.get}(x.$n.zp$t(i)), ${q}zp$t ${pf.get} $n ${q}+i.toString)") } pr( s" }") } @@ -136,11 +143,17 @@ object Generator { names.foreach{ n => pr( s" { // Scope for operations $o collection $n") pr( s" var x = new bench.generate.Things(${sayArrayI(sizes)})" ) - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => if (ordname(n) || !ord) { if (nojname(n)) { pr( s" timings(x, i => $o.$f(x.$n.c$t(i)), ${q}c$t $f $n${q})"); pr( s" timings(x, i => $o.$f(x.$n.i$t(i)), ${q}i$t $f $n${q})") + if (!nu) { + if (sqnname(n)) + pr( s" timings(x, i => $o.$f(x.$n.ts$t(i)), ${q}ts$t $f $n${q})"); + else + pr( s" timings(x, i => $o.$f(x.$n.tp$t(i)), ${q}tp$t $f $n${q})"); + } } if (sqnname(n)) { pr( s" timings(x, i => $o.$f(x.$n.ss$t(i)), ${q}ss$t $f $n${q})") @@ -184,20 +197,26 @@ object Generator { val m = sizes.map(_.length).getOrElse(new bench.generate.Things().N) allops.foreach{ case (o, t, fs) => names.foreach{ n => - parsefs(fs).foreach{ case (f, pf, ord) => + parsefs(fs).foreach{ case (f, pf, ord, nu) => for (i <- 0 until m) { if (ordname(n) || !ord) { if (nojname(n)) { - pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))"); + pr( s" @Benchmark def bench_c${t}_${f}_${n}_$i() = $o.$f(x.$n.c$t($i))") pr( s" @Benchmark def bench_i${t}_${f}_${n}_$i() = $o.$f(x.$n.i$t($i))") + if (!nu) { + if (sqnname(n)) + pr( s" @Benchmark def bench_ts${t}_${f}_${n}_$i() = $o.$f(x.$n.ts$t($i))") + else + pr( s" @Benchmark def bench_tp${t}_${f}_${n}_$i() = $o.$f(x.$n.tp$t($i))") + } } - if (sqnname(n)) { - pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") - //if (nojname(n)) - // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") - } + pr( s" @Benchmark def bench_ss${t}_${f}_${n}_$i() = $o.$f(x.$n.ss$t($i))") + //if (nojname(n)) + // pr( s" @Benchmark def bench_zs${t}_${f}_${n}_$i() = $o.$f(x.$n.zs$t($i))") if (parname(n) && pf.isDefined) { - pr( s" @Benchmark def bench_sp${t}_${f}_${n}_$i() = $o.$f(x.$n.sp$t($i))") + if (nojname(n)) + pr( s" @Benchmark def bench_cp${t}_${pf.get}_${n}_$i() = $o.${pf.get}(x.$n.c$t($i).par)") + pr( s" @Benchmark def bench_sp${t}_${pf.get}_${n}_$i() = $o.${pf.get}(x.$n.sp$t($i))") //if (nojname(n)) // pr( s" @Benchmark def bench_zp${t}_${f}_${n}_$i() = $o.$f(x.$n.zp$t($i))") } diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala index 38c3f4c..6208ac4 100644 --- a/benchmark/src/main/scala/bench/Operations.scala +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -2,6 +2,9 @@ package bench.operate import java.util.stream._ import java.util.{function => jf} + +import scala.collection.parallel.ParIterable + import scala.compat.java8.StreamConverters._ import scala.compat.java8.converterImpl._ import scala.compat.java8.collectionImpl._ @@ -25,16 +28,16 @@ object OnInt { def sum(i: Iterator[Int]): Int = i.sum def sum(s: IntStepper): Int = s.fold(0)(_ + _) def sum(s: IntStream): Int = s.sum - def psum(i: Iterable[Int]): Int = i.par.sum - def psum(s: IntStream): Int = s.parallel.sum + def psum(i: ParIterable[Int]): Int = i.sum + def psum(s: IntStream): Int = s.sum def trig(a: Array[Int]): Double = { var i = 0; var s = 0.0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } def trig(t: Traversable[Int]): Double = t.map(expensive).sum def trig(i: Iterator[Int]): Double = i.map(expensive).sum def trig(s: IntStepper): Double = s.fold(0.0)((x,i) => x + expensive(i)) def trig(s: IntStream): Double = s.mapToDouble(new jf.IntToDoubleFunction{ def applyAsDouble(i: Int) = expensive(i) }).sum - def ptrig(i: Iterable[Int]): Double = i.par.map(expensive).sum - def ptrig(s: IntStream): Double = trig(s.parallel) + def ptrig(i: ParIterable[Int]): Double = i.map(expensive).sum + def ptrig(s: IntStream): Double = trig(s) def fmc(a: Array[Int]): Int = { var s,i = 0; while (i < a.length) { if (i%7 == 1) s += (i/7)*i; i += 1 }; s } def fmc(t: Traversable[Int]): Int = t.filter(x => (x%7) == 1).map(x => (x/7)*x).sum @@ -43,8 +46,8 @@ object OnInt { filter(new jf.IntPredicate { def test(x: Int) = (x%7) == 1 }). map(new jf.IntUnaryOperator{ def applyAsInt(x: Int) = (x/7)*x }). sum - def pfmc(i: Iterable[Int]): Int = i.par.filter(x => (x%7) == 1).map(x => (x/7)*x).sum - def pfmc(s: IntStream): Int = fmc(s.parallel) + def pfmc(i: ParIterable[Int]): Int = i.filter(x => (x%7) == 1).map(x => (x/7)*x).sum + def pfmc(s: IntStream): Int = fmc(s) def mdtc(a: Array[Int]): Int = { var i = 1; while(i < a.length) { if ((a(i) << 1) >= 42) return i-1; i += 1 }; i - 1 } def mdtc(t: Traversable[Int]): Int = t.map(_ << 1).drop(1).takeWhile(_ < 42).size @@ -65,16 +68,16 @@ object OnString { def nbr(i: Iterator[String]): Int = i.count(s => s.charAt(s.length-1) < '5') def nbr(p: Stepper[String]): Int = p.fold(0)((i,s) => if (s.charAt(s.length-1) < '5') i+1 else i) def nbr(q: Stream[String]): Int = q.filter(new jf.Predicate[String] { def test(s: String) = s.charAt(s.length-1) < '5' }).count.toInt - def pnbr(i: Iterable[String]): Int = i.par.count(s => s.charAt(s.length-1) < '5') - def pnbr(q: Stream[String]): Int = nbr(q.parallel) + def pnbr(i: ParIterable[String]): Int = i.count(s => s.charAt(s.length-1) < '5') + def pnbr(q: Stream[String]): Int = nbr(q) def htrg(a: Array[String]): Double = { var s = 0.0; var i = 0; while (i < a.length) { s += expensive(a(i)); i += 1 }; s } def htrg(t: Traversable[String]): Double = t.map(expensive).sum def htrg(i: Iterator[String]): Double = i.map(expensive).sum def htrg(p: Stepper[String]): Double = p.fold(0.0)((x,s) => x + expensive(s)) def htrg(q: Stream[String]): Double = q.mapToDouble(new jf.ToDoubleFunction[String]{ def applyAsDouble(s: String) = expensive(s) }).sum - def phtrg(i: Iterable[String]): Double = i.par.map(expensive).sum - def phtrg(q: Stream[String]): Double = htrg(q.parallel) + def phtrg(i: ParIterable[String]): Double = i.map(expensive).sum + def phtrg(q: Stream[String]): Double = htrg(q) def fmc(a: Array[String]): Int = { var s, i = 0 @@ -94,9 +97,9 @@ object OnString { map[String](new jf.Function[String, String]{ def apply(x: String) = if (x.charAt(0) == '-') x.substring(1) else x }). filter(new jf.Predicate[String]{ def test(x: String) = x.length > 1 }). count.toInt - def pfmc(i: Iterable[String]): Int = - i.par.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) - def pfmc(q: Stream[String]): Int = fmc(q.parallel) + def pfmc(i: ParIterable[String]): Int = + i.filter(x => x.charAt(x.length-1) == '1').map(x => if (x.charAt(0) == '-') x.substring(1) else x).count(_.length > 1) + def pfmc(q: Stream[String]): Int = fmc(q) def mdtc(a: Array[String]): Int = { var i = 1 diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala new file mode 100644 index 0000000..df45ee9 --- /dev/null +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -0,0 +1,146 @@ +package bench.examine + +import scala.util._ +import scala.util.control.NonFatal + +object ParseJmhLog { + // Manual path to the log file (which may have been put there manually) + val logLocation = "results/jmhbench.log" + + // Warning--this is maintained manually! Please take care to keep it up to date. + val collectionNames = Map( + "arb" -> "collection.mutable.ArrayBuffer", + "arr" -> "Array", + "ars" -> "collection.mutable.ArraySeq", + "ast" -> "collection.mutable.ArrayStack", + "ils" -> "collection.immutable.ListSet", + "ish" -> "collection.immutable.HashSet", + "lhs" -> "collection.mutable.LinkedHashSet", + "lst" -> "collection.immutable.List", + "mhs" -> "collection.mutable.HashSet", + "muq" -> "collection.mutable.Queue", + "prq" -> "collection.mutable.PriorityQueue", + "que" -> "collection.immutable.Queue", + "stm" -> "collection.immutable.Stream", + "trs" -> "collection.immutable.TreeSet", + "vec" -> "collection.immutable.Vector", + "wra" -> "collection.mutable.WrappedArray", + "jix" -> "java.util.ArrayList", + "jln" -> "java.util.LinkedList" + ) + + // Warning--this is maintained manually! Please take care to keep it up to date. + val dataNames = Map( + "cI" -> "Int, base collection", + "cpI" -> "Int, par collection", + "iI" -> "Int, iterator on coll", + "ssI" -> "Int, serial stream", + "spI" -> "Int, parallel stream", + "tpI" -> "Int Stepper (can par)", + "tsI" -> "Int Stepper (seq only)", + "cS" -> "String, base collection", + "cpS" -> "String, par collection", + "iS" -> "String, iterator on coll", + "ssS" -> "String, serial stream", + "spS" -> "String, parallel stream", + "tpS" -> "String Stepper (can par)", + "tsS" -> "String Stepper (seq only)" + ) + val dataColumnWidth = dataNames.map(_._2).map(_.length).max + 1 + + // Warning--this is maintained manually! Please take care to keep it up to date. + val operationNames = Map( + "sum" -> "fast summation", + "psum" -> "fast parallel summation", + "nbr" -> "fast sum of lengths", + "pnbr" -> "fast parallel sum of lengths", + "trig" -> "slow trigonometry", + "ptrig" -> "slow parallel trigonometry", + "htrg" -> "slow trig on hashCode", + "phtrg" -> "slow parallel trig on hashCode", + "fmc" -> "filter/map/sum trio", + "pfmc" -> "parallel filter/map/sum trio", + "mdtc" -> "map/filter/take trio" + ) + + private def ensure(satisfied: Boolean)(not: => Unit) { + if (!satisfied) { + not + assert(satisfied) + } + } + + private def indicate(cols: Int, value: Double): String = { + val one = math.min((3*cols)/4, cols-5) + val me = math.rint(one*3*value).toInt + if (me <= 3*(cols-1)) { + val filled = + if ((me%3) != 0) "#"*(me/3) + (if ((me%3) == 1) "-" else "=") + else "#"*(me/3) + filled + " "*(cols - filled.length) + } + else "#"*(cols-4) + "~~# " + } + + case class Entry(op: String, coll: String, big: Boolean, data: String, speed: Double, errbar: Double) { + ensure(collectionNames contains coll){ println(coll) } + ensure(dataNames contains data){ println(data) } + ensure(operationNames contains op){ println(op) } + } + + def apply(f: java.io.File = new java.io.File(logLocation)) = { + val lines = { + val s = scala.io.Source.fromFile(f) + try { s.getLines().toVector } finally { s.close } + } + + val relevant = lines. + dropWhile(x => !(x contains "Run complete.")). + dropWhile(x => !(x contains "JmhBench.bench_")). + takeWhile(x => x contains "JmhBench.bench_"). + map{ x => + val ys = x.split("\\s+") + ys(1).split('_').drop(1) match { + case Array(dat, op, coll, n) => Entry (op, coll, n == "1", dat, ys(4).toDouble, ys(6).toDouble) + case _ => throw new Exception("Bad benchmark log line, please investigate manually.") + } + }. + toArray + + val normalized = relevant. + groupBy(e => (e.op, e.big, e.data.takeRight(1))). + mapValues{ vs => + val one = vs.find(e => e.coll == "arr" && e.data.startsWith("c")).get.speed + vs.map(v => v.copy(speed = v.speed/one, errbar = 100 * v.errbar/v.speed)) // Error bar in percent error from mean + }. + map(_._2). + toArray. + sortBy(_(0) match { case Entry(o, _, b, d, _, _) => (o, d.takeRight(1), b) }). + map(_.sortBy{ case Entry(_, c, _, d, _, _) => (c, d.dropRight(1)) }) + + normalized.foreach{ es => + println + println(">"*79) + println + var remaining = es.toList + while (remaining.nonEmpty) { + val (esa, esb) = remaining.span(_.coll == remaining.head.coll) + remaining = esb + println(operationNames(esa.head.op)) + println(if (esa.head.big) "10000 elements" else "10 elements") + println(collectionNames(esa.head.coll)) + esa.foreach{ e => + println( + s" %-${dataColumnWidth}s ".format(dataNames(e.data)) + + indicate(79 - (dataColumnWidth+3) - 16, e.speed) + + "%5.3f +- %5.1f %%".format(e.speed, e.errbar) + ) + } + if (remaining.nonEmpty) println + } + } + println + println("-"*79) + println + } +} diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index ed7607d..698bc23 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -11,7 +11,7 @@ trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends } /** Classes or objects implementing this trait create streams suitable for parallel use */ -trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { +trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any with MakesSequentialStream[A, SS] { def parStream: SS } From af5de577b0f56cf7a93a56eb105b55c5142bf2a5 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Fri, 8 Jan 2016 13:08:35 -0800 Subject: [PATCH 083/340] Example of Scala collection to Java 8 Stream from within Java. Also added a unit test to make sure the example compiles. --- .../java8/StreamConvertersExampleTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/scala/compat/java8/StreamConvertersExampleTest.java diff --git a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java new file mode 100644 index 0000000..e34a4d1 --- /dev/null +++ b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Typesafe Inc. + */ + +import org.junit.Test; + +import scala.collection.mutable.ArrayBuffer; +import scala.compat.java8.ScalaStreaming; + + +public class StreamConvertersExampleTest { + @Test + public void MakeAndUseArrayBuffer() { + ArrayBuffer ab = new ArrayBuffer(); + ab.$plus$eq("salmon"); + ab.$plus$eq("herring"); + assert( ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum() == 13 ); + } +} + From d3606b7896cb6383ec0057e05fcd647beaa94570 Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Wed, 17 Feb 2016 17:57:21 -0800 Subject: [PATCH 084/340] Describe how to get a Stream from Scala colls in Java. Also fixed the Scala example to actually run. --- README.md | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6f7b472..54fe1b1 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ obtain Java 8 Streams from Scala collections from within Java. For sequential operations, Scala's `iterator` almost always equals or exceeds the performance of a Java 8 stream. Thus, one should favor `iterator` (and its richer set of operations) over `seqStream` for general use. However, long -chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, +chains of processing of primitive types can sometimes benefit from the manually specialized methods in `DoubleStream`, `IntStream`, and `LongStream`. Note that although `iterator` typically has superior performance in a sequential context, the advantage is modest @@ -173,13 +173,14 @@ object Test { val m = collection.immutable.HashMap("fish" -> 2, "bird" -> 4) val s = m.parValueStream.sum // 6, potientially computed in parallel val t = m.seqKeyStream.toScala[List] // List("fish", "bird") - val a = t.accumulate // Accumulator[(String, Int)] + val a = m.accumulate // Accumulator[(String, Int)] - val n = a.splitter.fold(0)(_ + _._1.length) + + val n = a.stepper.fold(0)(_ + _._1.length) + a.parStream.count // 8 + 2 = 10 val b = java.util.Arrays.stream(Array(2L, 3L, 4L)). accumulate // LongAccumulator + val l = b.to[List] // List(2L, 3L, 4L) } ``` @@ -216,6 +217,34 @@ def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = #### Java Usage Example +To convert a Scala collection to a Java 8 Stream from within Java, it usually +suffices to call `ScalaStreaming.from(xs)` on your collection `xs`. If `xs` is +a map, you may wish to get the keys or values alone by using `fromKeys` or +`fromValues`. If the collection has an underlying representation that is not +efficiently parallelized (e.g. `scala.collection.immutable.List`), then +`fromAccumulated` (and `fromAccumulatedKeys` and `fromAccumulatedValues`) will +first gather the collection into an `Accumulator` and then return a stream over +that accumulator. If not running in parallel, `from` is preferable (faster and +less memory usage). + +Note that a Scala `Iterator` cannot fulfill the contract of a Java 8 Stream +(because it cannot support `trySplit` if it is called). Presently, one must +call `fromAccumulated` on the `Iterator` to cache it, even if the Stream will +be evaluated sequentially, or wrap it as a Java Iterator and use static +methods in `Spliterator` to wrap that as a `Spliterator` and then a `Stream`. + +Here is an example of conversion of a Scala collection within Java 8: + ```java -// TODO -- write converter and create example +import scala.collection.mutable.ArrayBuffer; +import scala.compat.java8.ScalaStreaming; + +public class StreamConvertersExample { + public int MakeAndUseArrayBuffer() { + ArrayBuffer ab = new ArrayBuffer(); + ab.$plus$eq("salmon"); + ab.$plus$eq("herring"); + return ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum(); // 6+7 = 13 + } +} ``` From 8c2313f62126db9a43ca355ebf52954c4cbf523b Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 29 Mar 2016 15:13:43 +0200 Subject: [PATCH 085/340] Use a self-type on `StepperLike` instead of `typedPrecisely` --- .../compat/java8/collectionImpl/Stepper.scala | 17 +++++------------ .../scala/scala/compat/java8/StepperTest.scala | 9 --------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 73c9740..7476ded 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -53,7 +53,7 @@ trait EfficientSubstep {} /** Provides functionality for Stepper while keeping track of a more precise type of the collection. */ -trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => +trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self: CC => /** Characteristics are bit flags that indicate runtime characteristics of this Stepper. * * - `Distinct` means that no duplicates exist @@ -90,9 +90,6 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self => */ def substep(): CC - /** Returns the precise underlying type of this `Stepper`. */ - def typedPrecisely: CC - /** Warns this `Stepper` that it is likely to be used in a parallel context (used for efficiency only) */ def anticipateParallelism: this.type = this @@ -236,8 +233,7 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def nextStep = next def tryAdvance(c: java.util.function.Consumer[_ >: A]): Boolean = if (hasNext) { c.accept(next); true } else false def tryStep(f: A => Unit): Boolean = if (hasNext) { f(next); true } else false - def trySplit() = substep match { case null => null; case x => x.typedPrecisely } - final def typedPrecisely: AnyStepper[A] = this + def trySplit() = substep override def spliterator: Spliterator[A] = this def seqStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, false) def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true) @@ -253,8 +249,7 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false - def trySplit() = substep match { case null => null; case x => x.typedPrecisely } - final def typedPrecisely: DoubleStepper = this + def trySplit() = substep override def spliterator: Spliterator[Double] = this.asInstanceOf[Spliterator[Double]] // Scala and Java disagree about whether it's java.lang.Double or double def seqStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, false) def parStream: java.util.stream.DoubleStream = java.util.stream.StreamSupport.doubleStream(this, true) @@ -270,8 +265,7 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false - def trySplit() = substep match { case null => null; case x => x.typedPrecisely } - final def typedPrecisely = this + def trySplit() = substep override def spliterator: Spliterator[Int] = this.asInstanceOf[Spliterator[Int]] // Scala and Java disagree about whether it's java.lang.Integer or int def seqStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, false) def parStream: java.util.stream.IntStream = java.util.stream.StreamSupport.intStream(this, true) @@ -287,8 +281,7 @@ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false - def trySplit() = substep match { case null => null; case x => x.typedPrecisely } - final def typedPrecisely = this + def trySplit() = substep override def spliterator: Spliterator[Long] = this.asInstanceOf[Spliterator[Long]] // Scala and Java disagree about whether it's java.lang.Long or long def seqStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, false) def parStream: java.util.stream.LongStream = java.util.stream.StreamSupport.longStream(this, true) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 18cbc10..561a980 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -21,7 +21,6 @@ class IncStepperA(private val size0: Long) extends NextStepper[Int] { i = sub.size0 sub } - def typedPrecisely = this } class IncStepperB(private val size0: Long) extends TryStepper[Int] { @@ -37,7 +36,6 @@ class IncStepperB(private val size0: Long) extends TryStepper[Int] { i = sub.size0 sub } - def typedPrecisely = this } class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { @@ -67,7 +65,6 @@ class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, In if (undersub == null) null else new MappingStepper(undersub, mapping) } - def typedPrecisely = this def spliterator: Spliterator[B] = new MappingSpliterator[A, B](underlying.spliterator, mapping) } @@ -211,12 +208,6 @@ class StepperTest { sources.foreach{ case (i,s) => if (i > 0) subs(0)(s)(x => { assertEquals(x.knownSize, 1L); 0 }, _ + _) } } - @Test - def consistentPrecision() { - sources.foreach{ case (_,s) => assert(s eq s.typedPrecisely) } - sources.foreach{ case (_,s) => subs(0)(s)(x => { assert(x eq x.typedPrecisely); 0}, _ + _) } - } - @Test def count_only() { sources.foreach{ case (i, s) => assertEquals(i, s.count) } From 3cbecca01189463de63fa9a18374a0c4d95afc24 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Tue, 29 Mar 2016 17:31:41 +0200 Subject: [PATCH 086/340] Turn wrappers into value classes and make them final --- .../java8/PrimitiveIteratorConversions.scala | 4 ++-- .../compat/java8/SpliteratorConverters.scala | 6 +++--- .../scala/compat/java8/StreamConverters.scala | 20 +++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 68d4394..3e0a10b 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -96,13 +96,13 @@ object PrimitiveIteratorConverters { } /** Provides conversions from Java `Iterator` to manually specialized `PrimitiveIterator` variants, when available */ - implicit class RichJavaIteratorToPrimitives[A](val underlying: JIterator[A]) extends AnyVal { + implicit final class RichJavaIteratorToPrimitives[A](private val underlying: JIterator[A]) extends AnyVal { /** Wraps this `java.util.Iterator` as a manually specialized variant, if possible */ def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromJava(underlying) } /** Provides conversions from Scala `Iterator` to manually specialized `PrimitiveIterator` variants, when available */ - implicit class RichIteratorToPrimitives[A](val underlying: Iterator[A]) extends AnyVal { + implicit final class RichIteratorToPrimitives[A](private val underlying: Iterator[A]) extends AnyVal { /** Wraps this `scala.collection.Iterator` as a manually specialized `java.util.PrimitiveIterator` variant, if possible */ def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromScala(underlying) } diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala index 1babaf3..a635c92 100644 --- a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -17,13 +17,13 @@ package SpliteratorConverters { package object SpliteratorConverters extends SpliteratorConverters.Priority2SpliteratorConverters { - implicit class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { + implicit final class SpliteratorOfDoubleToStepper(private val underlying: Spliterator.OfDouble) extends AnyVal { def stepper: DoubleStepper = Stepper.ofSpliterator(underlying) } - implicit class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { + implicit final class SpliteratorOfIntToStepper(private val underlying: Spliterator.OfInt) extends AnyVal { def stepper: IntStepper = Stepper.ofSpliterator(underlying) } - implicit class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { + implicit final class SpliteratorOfLongToStepper(private val underlying: Spliterator.OfLong) extends AnyVal { def stepper: LongStepper = Stepper.ofSpliterator(underlying) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 3999761..857cdff 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -208,25 +208,25 @@ extends Priority1StreamConverters with converterImpl.Priority1StepConverters with converterImpl.Priority1AccumulatorConverters { - implicit class EnrichDoubleArrayWithStream(a: Array[Double]) - extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { + implicit final class EnrichDoubleArrayWithStream(private val a: Array[Double]) + extends AnyVal with MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel } - implicit class EnrichIntArrayWithStream(a: Array[Int]) - extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { + implicit final class EnrichIntArrayWithStream(private val a: Array[Int]) + extends AnyVal with MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = java.util.Arrays.stream(a) def parStream: IntStream = seqStream.parallel } - implicit class EnrichLongArrayWithStream(a: Array[Long]) - extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { + implicit final class EnrichLongArrayWithStream(private val a: Array[Long]) + extends AnyVal with MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = java.util.Arrays.stream(a) def parStream: LongStream = seqStream.parallel } - implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { + implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { def streamAccumulate(stream: Stream[Double]): DoubleAccumulator = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger) } @@ -274,7 +274,7 @@ with converterImpl.Priority1AccumulatorConverters implicit val primitiveUnboxLongStream2 = primitiveUnboxLongStream.asInstanceOf[PrimitiveStreamUnboxer[java.lang.Long, LongStream]] - implicit class RichDoubleStream(stream: DoubleStream) { + implicit final class RichDoubleStream(private val stream: DoubleStream) extends AnyVal { def accumulate = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Double, Coll[Double]]): Coll[Double] = { @@ -287,7 +287,7 @@ with converterImpl.Priority1AccumulatorConverters } } - implicit class RichIntStream(stream: IntStream) { + implicit final class RichIntStream(private val stream: IntStream) extends AnyVal { def accumulate = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Int, Coll[Int]]): Coll[Int] = { @@ -300,7 +300,7 @@ with converterImpl.Priority1AccumulatorConverters } } - implicit class RichLongStream(stream: LongStream) { + implicit final class RichLongStream(private val stream: LongStream) extends AnyVal { def accumulate = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) def toScala[Coll[_]](implicit cbf: collection.generic.CanBuildFrom[Nothing, Long, Coll[Long]]): Coll[Long] = { From 84a12db1073555152ac14f20419cf29cd318d91a Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 13:39:43 +0200 Subject: [PATCH 087/340] Provide char-based Stepper for String as the default Stepper Both `charStepper` and `codepointStepper` are available through separate methods. The default `stepper` methods from `MakesIntStepper` is equivalent to `charStepper`. --- .../compat/java8/converterImpl/StepsString.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index a281068..2bfefe9 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -11,6 +11,12 @@ import Stepper._ // Stepper implementation // //////////////////////////// +private[java8] class StepperStringChar(underlying: String, _i0: Int, _iN: Int) + extends StepsIntLikeIndexed[StepperStringChar](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying.charAt(j) } else throwNSEE + def semiclone(half: Int) = new StepperStringChar(underlying, i0, half) +} + private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var iN: Int) extends IntStepper with EfficientSubstep { def characteristics() = NonNull def estimateSize = iN - i0 @@ -40,5 +46,7 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var ///////////////////////// final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { - @inline def stepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) -} + @inline def stepper: IntStepper with EfficientSubstep = charStepper + @inline def charStepper: IntStepper with EfficientSubstep = new StepperStringChar(underlying, 0, underlying.length) + @inline def codepointStepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) +} From 315c6ad5359d52ea3c636331b7eb16c4883d543f Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 13:51:42 +0200 Subject: [PATCH 088/340] Move EfficientSubstep up in inheritance hierarchy --- .../compat/java8/converterImpl/StepsLikeGapped.scala | 8 +++----- .../compat/java8/converterImpl/StepsLikeIndexed.scala | 8 +++----- .../compat/java8/converterImpl/StepsLikeSliced.scala | 8 +++----- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala index 0bb741b..f70b8b2 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala @@ -11,7 +11,9 @@ import Stepper._ * is used as a signal to look for more entries in the array. (This also * allows a subclass to traverse a sublist by updating `currentEntry`.) */ -private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub](protected val underlying: Array[AnyRef], protected var i0: Int, protected var iN: Int) + extends EfficientSubstep { + protected var currentEntry: AnyRef = null def semiclone(half: Int): Semi def characteristics(): Int = Ordered @@ -37,7 +39,6 @@ private[java8] abstract class AbstractStepsLikeGapped[Sub >: Null, Semi <: Sub]( private[java8] abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[A, _]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] - with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -47,7 +48,6 @@ private[java8] abstract class StepsLikeGapped[A, STA >: Null <: StepsLikeGapped[ private[java8] abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[DoubleStepper, STD](_underlying, _i0, _iN) with DoubleStepper - with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -57,7 +57,6 @@ private[java8] abstract class StepsDoubleLikeGapped[STD >: Null <: StepsDoubleLi private[java8] abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[IntStepper, STI](_underlying, _i0, _iN) with IntStepper - with EfficientSubstep {} /** Abstracts the process of stepping through an incompletely filled array of `AnyRefs` @@ -67,5 +66,4 @@ private[java8] abstract class StepsIntLikeGapped[STI >: Null <: StepsIntLikeGapp private[java8] abstract class StepsLongLikeGapped[STL >: Null <: StepsLongLikeGapped[_]](_underlying: Array[AnyRef], _i0: Int, _iN: Int) extends AbstractStepsLikeGapped[LongStepper, STL](_underlying, _i0, _iN) with LongStepper - with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index 175cf0d..d0b7419 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -6,7 +6,9 @@ import scala.compat.java8.collectionImpl._ import Stepper._ /** Abstracts all the generic operations of stepping over an indexable collection */ -private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub](protected var i0: Int, protected var iN: Int) + extends EfficientSubstep { + def semiclone(half: Int): Semi def characteristics(): Int = Ordered + Sized + SubSized def estimateSize(): Long = iN - i0 @@ -26,26 +28,22 @@ private[java8] abstract class AbstractStepsLikeIndexed[Sub >: Null, Semi <: Sub] private[java8] abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexed[A, _]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[AnyStepper[A], STA](_i0, _iN) with AnyStepper[A] - with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Doubles */ private[java8] abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper - with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Ints */ private[java8] abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper - with EfficientSubstep {} /** Abstracts the operation of stepping over an indexable collection of Longs */ private[java8] abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper - with EfficientSubstep {} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala index 4ec9b74..83609eb 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -9,7 +9,9 @@ import Stepper._ * `next` must update `i` but not `i0` so that later splitting steps can keep track of whether the * collection needs some sort of modification before transmission to the subclass. */ -private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) { +private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: Sub](protected var underlying: Coll, protected var i: Int, protected var iN: Int) + extends EfficientSubstep { + protected var i0: Int = i def semiclone(halfHint: Int): Semi // Must really do all the work for both this and cloned collection! def characteristics(): Int = Ordered @@ -21,26 +23,22 @@ private[java8] abstract class AbstractStepsLikeSliced[Coll, Sub >: Null, Semi <: private[java8] abstract class StepsLikeSliced[A, AA, STA >: Null <: StepsLikeSliced[A, AA, _]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, AnyStepper[A], STA](_underlying, _i0, _iN) with AnyStepper[A] - with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Doubles that can be efficiently sliced or otherwise subdivided */ private[java8] abstract class StepsDoubleLikeSliced[AA, STA >: Null <: StepsDoubleLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, DoubleStepper, STA](_underlying, _i0, _iN) with DoubleStepper - with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Ints that can be efficiently sliced or otherwise subdivided */ private[java8] abstract class StepsIntLikeSliced[AA, STA >: Null <: StepsIntLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, IntStepper, STA](_underlying, _i0, _iN) with IntStepper - with EfficientSubstep {} /** Abstracts the operation of stepping over a collection of Longs that can be efficiently sliced or otherwise subdivided */ private[java8] abstract class StepsLongLikeSliced[AA, STA >: Null <: StepsLongLikeSliced[AA, STA]](_underlying: AA, _i0: Int, _iN: Int) extends AbstractStepsLikeSliced[AA, LongStepper, STA](_underlying, _i0, _iN) with LongStepper - with EfficientSubstep {} From 6bb6a006496b2279fe77aa97cc90117180547890 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 15:15:34 +0200 Subject: [PATCH 089/340] Simplify MakesStepper design --- .../scala/compat/java8/StreamConverters.scala | 48 +++--- .../java8/converterImpl/MakesSteppers.scala | 147 ++---------------- .../java8/converterImpl/StepsArray.scala | 22 +-- .../java8/converterImpl/StepsBitSet.scala | 2 +- .../converterImpl/StepsFlatHashTable.scala | 8 +- .../java8/converterImpl/StepsHashTable.scala | 28 ++-- .../java8/converterImpl/StepsImmHashMap.scala | 14 +- .../java8/converterImpl/StepsImmHashSet.scala | 8 +- .../java8/converterImpl/StepsIndexedSeq.scala | 8 +- .../java8/converterImpl/StepsIterable.scala | 8 +- .../java8/converterImpl/StepsIterator.scala | 8 +- .../java8/converterImpl/StepsLinearSeq.scala | 8 +- .../compat/java8/converterImpl/StepsMap.scala | 14 +- .../java8/converterImpl/StepsRange.scala | 8 +- .../java8/converterImpl/StepsString.scala | 2 +- .../java8/converterImpl/StepsVector.scala | 8 +- 16 files changed, 106 insertions(+), 235 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 857cdff..d84418e 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -16,104 +16,104 @@ trait PrimitiveStreamUnboxer[A, S] { trait Priority5StreamConverters { // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. - implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[A]) + implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A]]) extends MakesSequentialStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeySeqStepper[K]) { + implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K]]) { def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) } - implicit class EnrichScalaCollectionWithValueSeqStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueSeqStepper[V]) { + implicit class EnrichScalaCollectionWithValueSeqStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V]]) { def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) } } trait Priority4StreamConverters extends Priority5StreamConverters { - implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleSeqStepper) + implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper]) extends MakesSequentialStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper) + implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]) extends MakesSequentialStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesLongSeqStepper) + implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper]) extends MakesSequentialStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) } - implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeySeqStepper) { + implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper]) { def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) } - implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeySeqStepper) { + implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper]) { def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) } - implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeySeqStepper) { + implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper]) { def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) } - implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueSeqStepper) { + implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper]) { def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) } - implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueSeqStepper) { + implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper]) { def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) } - implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueSeqStepper) { + implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper]) { def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) } } trait Priority3StreamConverters extends Priority4StreamConverters { - implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[A]) + implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A] with EfficientSubstep]) extends MakesSequentialStream[A, Stream[A]] with MakesParallelStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) } - implicit class EnrichAnyKeySteppableWithStream[K, CC](cc: CC)(implicit steppize: CC => MakesAnyKeyStepper[K]) { + implicit class EnrichAnyKeySteppableWithStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K] with EfficientSubstep]) { def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) } - implicit class EnrichAnyValueSteppableWithStream[V, CC](cc: CC)(implicit steppize: CC => MakesAnyValueStepper[V]) { + implicit class EnrichAnyValueSteppableWithStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V] with EfficientSubstep]) { def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) } } trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleStepper) + implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper with EfficientSubstep]) extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) } - implicit class EnrichDoubleKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleKeyStepper) { + implicit class EnrichDoubleKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper with EfficientSubstep]) { def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) } - implicit class EnrichDoubleValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesDoubleValueStepper) { + implicit class EnrichDoubleValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper with EfficientSubstep]) { def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntStepper) + implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]) extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) } - implicit class EnrichIntKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntKeyStepper) { + implicit class EnrichIntKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper with EfficientSubstep]) { def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) } - implicit class EnrichIntValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesIntValueStepper) { + implicit class EnrichIntValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper with EfficientSubstep]) { def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongStepper) + implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper with EfficientSubstep]) extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) } - implicit class EnrichLongKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongKeyStepper) { + implicit class EnrichLongKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper with EfficientSubstep]) { def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) } - implicit class EnrichLongValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesLongValueStepper) { + implicit class EnrichLongValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper with EfficientSubstep]) { def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index 698bc23..ab754eb 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -15,146 +15,17 @@ trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends A def parStream: SS } -/** Classes or objects implementing this trait create generic steppers suitable for sequential use. */ -trait MakesAnySeqStepper[A] extends Any { - /** Generates a fresh stepper over `A`s suitable for sequential use */ - def stepper: AnyStepper[A] +trait MakesStepper[T <: Stepper[_]] extends Any { + /** Generates a fresh stepper of type `T` */ + def stepper: T } -/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential use. */ -trait MakesAnyKeySeqStepper[A] extends Any { - /** Generates a fresh stepper over map keys of type `A` suitable for sequential use */ - def keyStepper: AnyStepper[A] +trait MakesKeyStepper[T <: Stepper[_]] extends Any { + /** Generates a fresh stepper of type `T` over map keys */ + def keyStepper: T } -/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential use. */ -trait MakesAnyValueSeqStepper[A] extends Any { - /** Generates a fresh stepper over map values of type `A` suitable for sequential use */ - def valueStepper: AnyStepper[A] -} - -/** Classes or objects implementing this trait create `Double` steppers suitable for sequential use. */ -trait MakesDoubleSeqStepper extends Any { - /** Generates a fresh stepper over `Double`s suitable for sequential use */ - def stepper: DoubleStepper -} - -/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential use. */ -trait MakesDoubleKeySeqStepper extends Any { - /** Generates a fresh stepper over map keys of type `Double` suitable for sequential use */ - def keyStepper: DoubleStepper -} - -/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential use. */ -trait MakesDoubleValueSeqStepper extends Any { - /** Generates a fresh stepper over map values of type `Double` suitable for sequential use */ - def valueStepper: DoubleStepper -} - -/** Classes or objects implementing this trait create `Int` steppers suitable for sequential use. */ -trait MakesIntSeqStepper extends Any { - /** Generates a fresh stepper over `Int`s suitable for sequential use */ - def stepper: IntStepper -} - -/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential use. */ -trait MakesIntKeySeqStepper extends Any { - /** Generates a fresh stepper over map keys of type `Int` suitable for sequential use */ - def keyStepper: IntStepper -} - -/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential use. */ -trait MakesIntValueSeqStepper extends Any { - /** Generates a fresh stepper over map values of type `Int` suitable for sequential use */ - def valueStepper: IntStepper -} - -/** Classes or objects implementing this trait create `Long` steppers suitable for sequential use. */ -trait MakesLongSeqStepper extends Any { - /** Generates a fresh stepper over `Long`s suitable for sequential use */ - def stepper: LongStepper -} - -/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential use. */ -trait MakesLongKeySeqStepper extends Any { - /** Generates a fresh stepper over map keys of type `Long` suitable for sequential use */ - def keyStepper: LongStepper -} - -/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential use. */ -trait MakesLongValueSeqStepper extends Any { - /** Generates a fresh stepper over map values of type `Long` suitable for sequential use */ - def valueStepper: LongStepper -} - -/** Classes or objects implementing this trait create generic steppers suitable for sequential or parallel use. */ -trait MakesAnyStepper[A] extends Any { - /** Generates a fresh stepper over `A`s that can be efficiently subdivided */ - def stepper: AnyStepper[A] with EfficientSubstep -} - -/** Classes or objects implementing this trait create generic steppers for map keys suitable for sequential or parallel use. */ -trait MakesAnyKeyStepper[A] extends Any { - /** Generates a fresh stepper over map keys of type `A` that can be efficiently subdivided */ - def keyStepper: AnyStepper[A] with EfficientSubstep -} - -/** Classes or objects implementing this trait create generic steppers for map values suitable for sequential or parallel use. */ -trait MakesAnyValueStepper[A] extends Any { - /** Generates a fresh stepper over map values of type `A` that can be efficiently subdivided */ - def valueStepper: AnyStepper[A] with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Double` steppers suitable for sequential or parallel use. */ -trait MakesDoubleStepper extends Any { - /** Generates a fresh stepper over `Double`s that can be efficiently subdivided */ - def stepper: DoubleStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Double` steppers for map keys suitable for sequential or parallel use. */ -trait MakesDoubleKeyStepper extends Any { - /** Generates a fresh stepper over map keys of type `Double` that can be efficiently subdivided */ - def keyStepper: DoubleStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Double` steppers for map values suitable for sequential or parallel use. */ -trait MakesDoubleValueStepper extends Any { - /** Generates a fresh stepper over map values of type `Double` that can be efficiently subdivided */ - def valueStepper: DoubleStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Int` steppers suitable for sequential or parallel use. */ -trait MakesIntStepper extends Any { - /** Generates a fresh stepper over `Int`s that can be efficiently subdivided */ - def stepper: IntStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Int` steppers for map keys suitable for sequential or parallel use. */ -trait MakesIntKeyStepper extends Any { - /** Generates a fresh stepper over map keys of type `Int` that can be efficiently subdivided */ - def keyStepper: IntStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Int` steppers for map values suitable for sequential or parallel use. */ -trait MakesIntValueStepper extends Any { - /** Generates a fresh stepper over map values of type `Int` that can be efficiently subdivided */ - def valueStepper: IntStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Long` steppers suitable for sequential or parallel use. */ -trait MakesLongStepper extends Any { - /** Generates a fresh stepper over `Long`s that can be efficiently subdivided */ - def stepper: LongStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Long` steppers for map keys suitable for sequential or parallel use. */ -trait MakesLongKeyStepper extends Any { - /** Generates a fresh stepper over map keys of type `Long` that can be efficiently subdivided */ - def keyStepper: LongStepper with EfficientSubstep -} - -/** Classes or objects implementing this trait create `Long` steppers for map values suitable for sequential or parallel use. */ -trait MakesLongValueStepper extends Any { - /** Generates a fresh stepper over map values of type `Long` that can be efficiently subdivided */ - def valueStepper: LongStepper with EfficientSubstep +trait MakesValueStepper[T <: Stepper[_]] extends Any { + /** Generates a fresh stepper of type `T` over map values */ + def valueStepper: T } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index e19e7ec..e4f6f01 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -81,46 +81,46 @@ extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { +final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) } -final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesAnyStepper[A] { +final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) } -final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesAnyStepper[Unit] { +final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesStepper[AnyStepper[Unit] with EfficientSubstep] { @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) } -final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesAnyStepper[Boolean] { +final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesStepper[AnyStepper[Boolean] with EfficientSubstep] { @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } -final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesAnyStepper[Byte] { +final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesStepper[AnyStepper[Byte] with EfficientSubstep] { @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) } -final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesAnyStepper[Char] { +final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesStepper[AnyStepper[Char] with EfficientSubstep] { @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) } -final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesAnyStepper[Short] { +final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesStepper[AnyStepper[Short] with EfficientSubstep] { @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) } -final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesAnyStepper[Float] { +final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesStepper[AnyStepper[Float] with EfficientSubstep] { @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) } -final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesDoubleStepper { +final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) } -final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesIntStepper { +final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) } -final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesLongStepper { +final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala index b4ab4ea..4c9436c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -53,7 +53,7 @@ extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { // Value class adapter // ///////////////////////// -final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesIntStepper { +final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { def stepper: IntStepper with EfficientSubstep = { val bits: Array[Long] = underlying match { case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index 5b8a55a..fb28870 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -39,28 +39,28 @@ extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { // Value class adapters // ////////////////////////// -final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesAnyStepper[A] { +final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = { val tbl = CollectionInternals.getTable(underlying) new StepsAnyFlatHashTable(tbl, 0, tbl.length) } } -final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesDoubleStepper { +final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { @inline def stepper: DoubleStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable(underlying) new StepsDoubleFlatHashTable(tbl, 0, tbl.length) } } -final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesIntStepper { +final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable(underlying) new StepsIntFlatHashTable(tbl, 0, tbl.length) } } -final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesLongStepper { +final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable(underlying) new StepsLongFlatHashTable(tbl, 0, tbl.length) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala index d1d611b..db68bb7 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -141,7 +141,7 @@ extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInst // Steppers for keys (type of HashEntry doesn't matter) final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) -extends AnyVal with MakesAnyKeyStepper[K] { +extends AnyVal with MakesKeyStepper[AnyStepper[K] with EfficientSubstep] { @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, HE](underlying) new StepsAnyHashTableKey(tbl, 0, tbl.length) @@ -149,7 +149,7 @@ extends AnyVal with MakesAnyKeyStepper[K] { } final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) -extends AnyVal with MakesDoubleKeyStepper { +extends AnyVal with MakesKeyStepper[DoubleStepper with EfficientSubstep] { @inline def keyStepper: DoubleStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[Double, HE](underlying) new StepsDoubleHashTableKey(tbl, 0, tbl.length) @@ -157,7 +157,7 @@ extends AnyVal with MakesDoubleKeyStepper { } final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) -extends AnyVal with MakesIntKeyStepper { +extends AnyVal with MakesKeyStepper[IntStepper with EfficientSubstep] { @inline def keyStepper: IntStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[Int, HE](underlying) new StepsIntHashTableKey(tbl, 0, tbl.length) @@ -165,7 +165,7 @@ extends AnyVal with MakesIntKeyStepper { } final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) -extends AnyVal with MakesLongKeyStepper { +extends AnyVal with MakesKeyStepper[LongStepper with EfficientSubstep] { @inline def keyStepper: LongStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[Long, HE](underlying) new StepsLongHashTableKey(tbl, 0, tbl.length) @@ -176,7 +176,7 @@ extends AnyVal with MakesLongKeyStepper { // (both for key-value pair and for values alone) final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) -extends AnyVal with MakesAnyStepper[(K, V)] { +extends AnyVal with MakesStepper[AnyStepper[(K,V)] with EfficientSubstep] { @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTable(tbl, 0, tbl.length) @@ -184,7 +184,7 @@ extends AnyVal with MakesAnyStepper[(K, V)] { } final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) -extends AnyVal with MakesAnyValueStepper[V] { +extends AnyVal with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) @@ -192,7 +192,7 @@ extends AnyVal with MakesAnyValueStepper[V] { } final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) -extends AnyVal with MakesDoubleValueStepper { +extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) @@ -200,7 +200,7 @@ extends AnyVal with MakesDoubleValueStepper { } final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) -extends AnyVal with MakesIntValueStepper { +extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) @@ -208,7 +208,7 @@ extends AnyVal with MakesIntValueStepper { } final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) -extends AnyVal with MakesLongValueStepper { +extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) @@ -219,7 +219,7 @@ extends AnyVal with MakesLongValueStepper { // (both for key-value pair and for values alone) final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) -extends AnyVal with MakesAnyStepper[(K,V)] { +extends AnyVal with MakesStepper[AnyStepper[(K,V)] with EfficientSubstep] { @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTable(tbl, 0, tbl.length) @@ -227,7 +227,7 @@ extends AnyVal with MakesAnyStepper[(K,V)] { } final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) -extends AnyVal with MakesAnyValueStepper[V] { +extends AnyVal with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) @@ -235,7 +235,7 @@ extends AnyVal with MakesAnyValueStepper[V] { } final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) -extends AnyVal with MakesDoubleValueStepper { +extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { @inline def valueStepper: DoubleStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) @@ -243,7 +243,7 @@ extends AnyVal with MakesDoubleValueStepper { } final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) -extends AnyVal with MakesIntValueStepper { +extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { @inline def valueStepper: IntStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) @@ -251,7 +251,7 @@ extends AnyVal with MakesIntValueStepper { } final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) -extends AnyVal with MakesLongValueStepper { +extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { @inline def valueStepper: LongStepper with EfficientSubstep = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala index 5cd58cb..d10b9a8 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -126,33 +126,33 @@ extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlyin ////////////////////////// final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) -extends AnyVal with MakesAnyStepper[(K, V)] with MakesAnyKeyStepper[K] with MakesAnyValueStepper[V] { +extends AnyVal with MakesStepper[AnyStepper[(K, V)] with EfficientSubstep] with MakesKeyStepper[AnyStepper[K] with EfficientSubstep] with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) } -final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesDoubleKeyStepper { +final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesKeyStepper[DoubleStepper with EfficientSubstep] { @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) } -final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesDoubleValueStepper { +final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) } -final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesIntKeyStepper { +final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesKeyStepper[IntStepper with EfficientSubstep] { @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) } -final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesIntValueStepper { +final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) } -final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesLongKeyStepper { +final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesKeyStepper[LongStepper with EfficientSubstep] { @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) } -final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesLongValueStepper { +final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala index 2fdfce6..75e0c7a 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -39,18 +39,18 @@ extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { // Value class adapters // ////////////////////////// -final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesAnyStepper[A] { +final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) } -final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesDoubleStepper { +final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) } -final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesIntStepper { +final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) } -final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesLongStepper { +final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index 6209121..bf00f35 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -39,18 +39,18 @@ extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesAnyStepper[A] { +final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) } -final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesDoubleStepper { +final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) } -final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesIntStepper { +final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) } -final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesLongStepper { +final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala index 8e1e494..0623119 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -10,18 +10,18 @@ import Stepper._ // Iterables just defer to iterator unless they can pattern match something better. // TODO: implement pattern matching! -final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesAnySeqStepper[A] { +final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesStepper[AnyStepper[A]] { @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) } -final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesDoubleSeqStepper { +final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesStepper[DoubleStepper] { @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) } -final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesIntSeqStepper { +final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesStepper[IntStepper] { @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) } -final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesLongSeqStepper { +final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesStepper[LongStepper] { @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala index a87f28d..89fa367 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -39,19 +39,19 @@ extends StepsLongLikeIterator[StepsLongIterator](_underlying) { // Value class adapters // ////////////////////////// -final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesAnySeqStepper[A] { +final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesStepper[AnyStepper[A]] { @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) } -final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesDoubleSeqStepper { +final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesStepper[DoubleStepper] { @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) } -final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesIntSeqStepper { +final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesStepper[IntStepper] { @inline def stepper: IntStepper = new StepsIntIterator(underlying) } -final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesLongSeqStepper { +final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesStepper[LongStepper] { @inline def stepper: LongStepper = new StepsLongIterator(underlying) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index d310560..978bc33 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -47,18 +47,18 @@ extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { // Value class adapters // ////////////////////////// -final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesAnySeqStepper[A] { +final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesStepper[AnyStepper[A]] { @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) } -final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesDoubleSeqStepper { +final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesStepper[DoubleStepper] { @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) } -final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesIntSeqStepper { +final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesStepper[IntStepper] { @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) } -final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesLongSeqStepper { +final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesStepper[LongStepper] { @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index e5c072b..684892c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -10,32 +10,32 @@ import Stepper._ // Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching // TODO: implement pattern matching -final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesAnyKeySeqStepper[K] with MakesAnyValueSeqStepper[V] { +final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyStepper[AnyStepper[K]] with MakesValueStepper[AnyStepper[V]] { // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) } -final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesDoubleKeySeqStepper { +final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesKeyStepper[DoubleStepper] { def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) } -final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesDoubleValueSeqStepper { +final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesValueStepper[DoubleStepper] { def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) } -final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesIntKeySeqStepper { +final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesKeyStepper[IntStepper] { def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) } -final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesIntValueSeqStepper { +final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesValueStepper[IntStepper] { def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) } -final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesLongKeySeqStepper { +final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesKeyStepper[LongStepper] { def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) } -final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesLongValueSeqStepper { +final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesValueStepper[LongStepper] { def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index bde77dc..e60acee 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -39,18 +39,18 @@ extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesIntStepper { +final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) } -final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesAnyStepper[T] { +final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesStepper[AnyStepper[T] with EfficientSubstep] { @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) } -final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesIntStepper { +final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) } -final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesLongStepper { +final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index 2bfefe9..de937b8 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -45,7 +45,7 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var // Value class adapter // ///////////////////////// -final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesIntStepper { +final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = charStepper @inline def charStepper: IntStepper with EfficientSubstep = new StepperStringChar(underlying, 0, underlying.length) @inline def codepointStepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index e3188f0..132f89b 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -134,18 +134,18 @@ with StepsVectorLike[Long] { // Value class adapters // ////////////////////////// -final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesAnyStepper[A] { +final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) } -final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesDoubleStepper { +final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) } -final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesIntStepper { +final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) } -final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesLongStepper { +final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) } From 44d17c692eef848dcb0af64107b99e52f1b0ebae Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 15:54:06 +0200 Subject: [PATCH 090/340] =?UTF-8?q?Abstract=20over=20=E2=80=9Cwith=20Effic?= =?UTF-8?q?ientSubstep=E2=80=9D=20in=20stream=20conversions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids the duplication of `seqStream` etc. method for collections that also support parallel streams. --- .../scala/compat/java8/StreamConverters.scala | 122 ++++++++---------- .../java8/converterImpl/MakesSteppers.scala | 8 +- 2 files changed, 56 insertions(+), 74 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index d84418e..2c6affc 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -14,10 +14,20 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority5StreamConverters { +trait Priority3StreamConverters { + implicit class EnrichAnySteppableWithParStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A] with EfficientSubstep]) + extends MakesParallelStream[A, Stream[A]] { + def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichAnyKeySteppableWithParKeyStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K] with EfficientSubstep]) { + def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichAnyValueSteppableWithParValueStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V] with EfficientSubstep]) { + def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) + } // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A]]) - extends MakesSequentialStream[A, Stream[A]] { + extends MakesSequentialStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K]]) { @@ -28,94 +38,66 @@ trait Priority5StreamConverters { } } -trait Priority4StreamConverters extends Priority5StreamConverters { +trait Priority2StreamConverters extends Priority3StreamConverters { + implicit class EnrichDoubleSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper with EfficientSubstep]) + extends MakesParallelStream[java.lang.Double, DoubleStream] { + def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichDoubleKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper with EfficientSubstep]) { + def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichDoubleValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper with EfficientSubstep]) { + def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) + } + implicit class EnrichIntSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]) + extends MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichIntKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper with EfficientSubstep]) { + def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichIntValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper with EfficientSubstep]) { + def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) + } + implicit class EnrichLongSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper with EfficientSubstep]) + extends MakesParallelStream[java.lang.Long, LongStream] { + def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) + } + implicit class EnrichLongKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper with EfficientSubstep]) { + def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) + } + implicit class EnrichLongValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper with EfficientSubstep]) { + def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) + } implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper]) - extends MakesSequentialStream[java.lang.Double, DoubleStream] { + extends MakesSequentialStream[java.lang.Double, DoubleStream] { def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) - } + } implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]) - extends MakesSequentialStream[java.lang.Integer, IntStream] { + extends MakesSequentialStream[java.lang.Integer, IntStream] { def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) - } + } implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper]) - extends MakesSequentialStream[java.lang.Long, LongStream] { + extends MakesSequentialStream[java.lang.Long, LongStream] { def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) } implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper]) { def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) - } + } implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper]) { def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) - } + } implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper]) { def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) } implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper]) { def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) - } - implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper]) { - def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) - } - implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper]) { - def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) - } -} - -trait Priority3StreamConverters extends Priority4StreamConverters { - implicit class EnrichAnySteppableWithStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A] with EfficientSubstep]) - extends MakesSequentialStream[A, Stream[A]] with MakesParallelStream[A, Stream[A]] { - def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) - def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichAnyKeySteppableWithStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K] with EfficientSubstep]) { - def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) - def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichAnyValueSteppableWithStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V] with EfficientSubstep]) { - def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) - def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) - } -} - -trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichDoubleSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper with EfficientSubstep]) - extends MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { - def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) - def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichDoubleKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper with EfficientSubstep]) { - def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) - def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichDoubleValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper with EfficientSubstep]) { - def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) - def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichIntSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]) - extends MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { - def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) - def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichIntKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper with EfficientSubstep]) { - def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) - def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichIntValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper with EfficientSubstep]) { + implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper]) { def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) - def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) } - implicit class EnrichLongSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper with EfficientSubstep]) - extends MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { - def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) - def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichLongKeySteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper with EfficientSubstep]) { - def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) - def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichLongValueSteppableWithStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper with EfficientSubstep]) { + implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper]) { def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) - def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index ab754eb..55c31f5 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -11,21 +11,21 @@ trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends } /** Classes or objects implementing this trait create streams suitable for parallel use */ -trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any with MakesSequentialStream[A, SS] { +trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { def parStream: SS } -trait MakesStepper[T <: Stepper[_]] extends Any { +trait MakesStepper[+T <: Stepper[_]] extends Any { /** Generates a fresh stepper of type `T` */ def stepper: T } -trait MakesKeyStepper[T <: Stepper[_]] extends Any { +trait MakesKeyStepper[+T <: Stepper[_]] extends Any { /** Generates a fresh stepper of type `T` over map keys */ def keyStepper: T } -trait MakesValueStepper[T <: Stepper[_]] extends Any { +trait MakesValueStepper[+T <: Stepper[_]] extends Any { /** Generates a fresh stepper of type `T` over map values */ def valueStepper: T } From 23ea66ac403d4cebb465b5e85aac467ffbfef135 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 18:02:54 +0200 Subject: [PATCH 091/340] Mark primitive AccumulatorSteppers as NONNULL --- .../scala/compat/java8/collectionImpl/DoubleAccumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/IntAccumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/LongAccumulator.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index b99ba7d..07d6b42 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -246,7 +246,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED + def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index 253119e..0747deb 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -253,7 +253,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED + def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 270d400..285d275 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -247,7 +247,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED + def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N From 061de4f9a87c39e2ed8366ea53b7974c4d4f63de Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 30 Mar 2016 18:52:47 +0200 Subject: [PATCH 092/340] =?UTF-8?q?Align=20`ScalaStreaming`=20names=20with?= =?UTF-8?q?=20Java=E2=80=99s=20`StreamSupport`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Streaming.java => ScalaStreamSupport.java} | 166 +++++++++--------- .../java8/StreamConvertersExampleTest.java | 4 +- 2 files changed, 85 insertions(+), 85 deletions(-) rename src/main/java/scala/compat/java8/{ScalaStreaming.java => ScalaStreamSupport.java} (82%) diff --git a/src/main/java/scala/compat/java8/ScalaStreaming.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java similarity index 82% rename from src/main/java/scala/compat/java8/ScalaStreaming.java rename to src/main/java/scala/compat/java8/ScalaStreamSupport.java index 9367361..54d29d8 100644 --- a/src/main/java/scala/compat/java8/ScalaStreaming.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -5,7 +5,7 @@ import java.util.stream.*; import scala.compat.java8.runtime.CollectionInternals; -public class ScalaStreaming { +public class ScalaStreamSupport { ///////////////////// // Generic Streams // ///////////////////// @@ -18,7 +18,7 @@ public class ScalaStreaming { * @param coll The IndexedSeq to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.IndexedSeq coll) { + public static Stream stream(scala.collection.IndexedSeq coll) { return StreamSupport.stream(new StepsAnyIndexedSeq(coll, 0, coll.length()), false); } @@ -30,7 +30,7 @@ public static Stream from(scala.collection.IndexedSeq coll) { * @param coll The immutable.HashMap to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromKeys(scala.collection.immutable.HashMap coll) { + public static Stream streamKeys(scala.collection.immutable.HashMap coll) { return StreamSupport.stream(new StepsAnyImmHashMapKey(coll, 0, coll.size()), false); } @@ -42,7 +42,7 @@ public static Stream fromKeys(scala.collection.immutable.HashMap Stream fromValues(scala.collection.immutable.HashMap coll) { + public static Stream streamValues(scala.collection.immutable.HashMap coll) { return StreamSupport.stream(new StepsAnyImmHashMapValue(coll, 0, coll.size()), false); } @@ -55,7 +55,7 @@ public static Stream fromValues(scala.collection.immutable.HashMap Stream< scala.Tuple2 > from(scala.collection.immutable.HashMap coll) { + public static Stream< scala.Tuple2 > stream(scala.collection.immutable.HashMap coll) { return StreamSupport.stream(new StepsAnyImmHashMap(coll, 0, coll.size()), false); } @@ -67,7 +67,7 @@ public static Stream< scala.Tuple2 > from(scala.collection.immutabl * @param coll The immutable.HashSet to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.immutable.HashSet coll) { + public static Stream stream(scala.collection.immutable.HashSet coll) { return StreamSupport.stream(new StepsAnyImmHashSet(coll.iterator(), coll.size()), false); } @@ -79,7 +79,7 @@ public static Stream from(scala.collection.immutable.HashSet coll) { * @param coll The mutable.HashMap to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromKeys(scala.collection.mutable.HashMap coll) { + public static Stream streamKeys(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.stream(new StepsAnyHashTableKey(tbl, 0, tbl.length), false); } @@ -92,7 +92,7 @@ public static Stream fromKeys(scala.collection.mutable.HashMap coll * @param coll The mutable.HashMap to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromValues(scala.collection.mutable.HashMap coll) { + public static Stream streamValues(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.stream(new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length), false); } @@ -106,7 +106,7 @@ public static Stream fromValues(scala.collection.mutable.HashMap Stream< scala.Tuple2 > from(scala.collection.mutable.HashMap coll) { + public static Stream< scala.Tuple2 > stream(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry< K, scala.collection.mutable.DefaultEntry >[] tbl = CollectionInternals.getTable(coll); return StreamSupport.stream(new StepsAnyDefaultHashTable(tbl, 0, tbl.length), false); @@ -120,7 +120,7 @@ public static Stream< scala.Tuple2 > from(scala.collection.mutable. * @param coll The mutable.HashSet to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.mutable.HashSet coll) { + public static Stream stream(scala.collection.mutable.HashSet coll) { Object[] tbl = CollectionInternals.getTable(coll); return StreamSupport.stream(new StepsAnyFlatHashTable(tbl, 0, tbl.length), false); } @@ -133,7 +133,7 @@ public static Stream from(scala.collection.mutable.HashSet coll) { * @param coll The Vector to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.immutable.Vector coll) { + public static Stream stream(scala.collection.immutable.Vector coll) { return StreamSupport.stream(new StepsAnyVector(coll, 0, coll.length()), false); } @@ -141,13 +141,13 @@ public static Stream from(scala.collection.immutable.Vector coll) { * Generates a Stream that traverses the keys of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the fromAccumulatedKeys method instead, but + * For efficient parallel operation, use the streamAccumulatedKeys method instead, but * note that this creates a new collection containing the Map's keys. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromKeys(scala.collection.Map coll) { + public static Stream streamKeys(scala.collection.Map coll) { return StreamSupport.stream(new StepsAnyIterator(coll.keysIterator()), false); } @@ -155,13 +155,13 @@ public static Stream fromKeys(scala.collection.Map coll) { * Generates a Stream that traverses the values of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the fromAccumulatedValues method instead, but + * For efficient parallel operation, use the streamAccumulatedValues method instead, but * note that this creates a new collection containing the Map's values. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromValues(scala.collection.Map coll) { + public static Stream streamValues(scala.collection.Map coll) { return StreamSupport.stream(new StepsAnyIterator(coll.valuesIterator()), false); } @@ -169,13 +169,13 @@ public static Stream fromValues(scala.collection.Map coll) { * Generates a Stream that traverses the key-value pairs of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the fromAccumulated method instead, but + * For efficient parallel operation, use the streamAccumulated method instead, but * note that this creates a new collection containing the Map's key-value pairs. * * @param coll The Map to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream< scala.Tuple2 > from(scala.collection.Map coll) { + public static Stream< scala.Tuple2 > stream(scala.collection.Map coll) { return StreamSupport.stream(new StepsAnyIterator< scala.Tuple2 >(coll.iterator()), false); } @@ -183,13 +183,13 @@ public static Stream< scala.Tuple2 > from(scala.collection.Map * Generates a Stream that traverses a scala.collection.Iterator. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the fromAccumulated method instead, + * For efficient parallel operation, use the streamAccumulated method instead, * but note that this creates a copy of the contents of the Iterator. * * @param coll The scala.collection.Iterator to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.Iterator coll) { + public static Stream stream(scala.collection.Iterator coll) { return StreamSupport.stream(new StepsAnyIterator(coll), false); } @@ -197,13 +197,13 @@ public static Stream from(scala.collection.Iterator coll) { * Generates a Stream that traverses a scala.collection.Iterable. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the fromAccumulated method instead, + * For efficient parallel operation, use the streamAccumulated method instead, * but note that this creates a copy of the contents of the Iterable * * @param coll The scala.collection.Iterable to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream from(scala.collection.Iterable coll) { + public static Stream stream(scala.collection.Iterable coll) { return StreamSupport.stream(new StepsAnyIterator(coll.iterator()), false); } @@ -216,7 +216,7 @@ public static Stream from(scala.collection.Iterable coll) { * @param coll The collection to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromAccumulated(scala.collection.TraversableOnce coll) { + public static Stream streamAccumulated(scala.collection.TraversableOnce coll) { scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll); return StreamSupport.stream(acc.spliterator(), false); } @@ -230,7 +230,7 @@ public static Stream fromAccumulated(scala.collection.TraversableOnce * @param coll The map containing keys to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromAccumulatedKeys(scala.collection.Map coll) { + public static Stream streamAccumulatedKeys(scala.collection.Map coll) { scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.keysIterator()); return StreamSupport.stream(acc.spliterator(), false); } @@ -244,7 +244,7 @@ public static Stream fromAccumulatedKeys(scala.collection.Map coll) * @param coll The map containing values to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static Stream fromAccumulatedValues(scala.collection.Map coll) { + public static Stream streamAccumulatedValues(scala.collection.Map coll) { scala.compat.java8.collectionImpl.Accumulator acc = scala.compat.java8.collectionImpl.Accumulator.from(coll.valuesIterator()); return StreamSupport.stream(acc.spliterator(), false); } @@ -261,7 +261,7 @@ public static Stream fromAccumulatedValues(scala.collection.Map col * @param coll The IndexedSeq to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFrom(scala.collection.IndexedSeq coll) { + public static DoubleStream doubleStream(scala.collection.IndexedSeq coll) { return StreamSupport.doubleStream(new StepsDoubleIndexedSeq(coll, 0, coll.length()), false); } @@ -273,7 +273,7 @@ public static DoubleStream doubleFrom(scala.collection.IndexedSeq coll) * @param coll The immutable.HashMap to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromKeys(scala.collection.immutable.HashMap coll) { + public static DoubleStream doubleStreamKeys(scala.collection.immutable.HashMap coll) { return StreamSupport.doubleStream(new StepsDoubleImmHashMapKey(coll, 0, coll.size()), false); } @@ -285,7 +285,7 @@ public static DoubleStream doubleFromKeys(scala.collection.immutable.HashMap coll) { + public static DoubleStream doubleStreamValues(scala.collection.immutable.HashMap coll) { return StreamSupport.doubleStream(new StepsDoubleImmHashMapValue(coll, 0, coll.size()), false); } @@ -297,7 +297,7 @@ public static DoubleStream doubleFromValues(scala.collection.immutable.HashMap coll) { + public static DoubleStream doubleStream(scala.collection.immutable.HashSet coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.doubleStream(new StepsDoubleImmHashSet(iter, coll.size()), false); } @@ -310,7 +310,7 @@ public static DoubleStream doubleFrom(scala.collection.immutable.HashSet * @param coll The mutable.HashMap to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromKeys(scala.collection.mutable.HashMap coll) { + public static DoubleStream doubleStreamKeys(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.doubleStream(new StepsDoubleHashTableKey(tbl, 0, tbl.length), false); } @@ -323,7 +323,7 @@ public static DoubleStream doubleFromKeys(scala.collection.mutable.HashMap coll) { + public static DoubleStream doubleStreamValues(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.doubleStream(new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length), false); } @@ -336,7 +336,7 @@ public static DoubleStream doubleFromValues(scala.collection.mutable.HashMap coll) { + public static DoubleStream doubleStream(scala.collection.mutable.HashSet coll) { Object[] tbl = CollectionInternals.getTable(coll); return StreamSupport.doubleStream(new StepsDoubleFlatHashTable(tbl, 0, tbl.length), false); } @@ -349,7 +349,7 @@ public static DoubleStream doubleFrom(scala.collection.mutable.HashSet c * @param coll The Vector to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFrom(scala.collection.immutable.Vector coll) { + public static DoubleStream doubleStream(scala.collection.immutable.Vector coll) { scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; return StreamSupport.doubleStream(new StepsDoubleVector(erased, 0, coll.length()), false); } @@ -358,13 +358,13 @@ public static DoubleStream doubleFrom(scala.collection.immutable.Vector * Generates a DoubleStream that traverses the double-valued keys of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleFromAccumulatedKeys method instead, but + * For efficient parallel operation, use the doubleStreamAccumulatedKeys method instead, but * note that this creates a new collection containing the Map's keys. * * @param coll The Map to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromKeys(scala.collection.Map coll) { + public static DoubleStream doubleStreamKeys(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); } @@ -373,13 +373,13 @@ public static DoubleStream doubleFromKeys(scala.collection.Map coll) * Generates a DoubleStream that traverses the double-valued values of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleFromAccumulatedValues method instead, but + * For efficient parallel operation, use the doubleStreamAccumulatedValues method instead, but * note that this creates a new collection containing the Map's values. * * @param coll The Map to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromValues(scala.collection.Map coll) { + public static DoubleStream doubleStreamValues(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); } @@ -388,13 +388,13 @@ public static DoubleStream doubleFromValues(scala.collection.Map coll * Generates a DoubleStream that traverses a double-valued scala.collection.Iterator. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleFromAccumulated method instead, + * For efficient parallel operation, use the doubleStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterator. * * @param coll The scala.collection.Iterator to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFrom(scala.collection.Iterator coll) { + public static DoubleStream doubleStream(scala.collection.Iterator coll) { return StreamSupport.doubleStream(new StepsDoubleIterator((scala.collection.Iterator)coll), false); } @@ -402,13 +402,13 @@ public static DoubleStream doubleFrom(scala.collection.Iterator coll) { * Generates a DoubleStream that traverses a double-valued scala.collection.Iterable. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the doubleFromAccumulated method instead, + * For efficient parallel operation, use the doubleStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterable. * * @param coll The scala.collection.Iterable to traverse * @return A DoubleStream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFrom(scala.collection.Iterable coll) { + public static DoubleStream doubleStream(scala.collection.Iterable coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.doubleStream(new StepsDoubleIterator(iter), false); } @@ -422,7 +422,7 @@ public static DoubleStream doubleFrom(scala.collection.Iterable coll) { * @param coll The collection to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromAccumulated(scala.collection.TraversableOnce coll) { + public static DoubleStream doubleStreamAccumulated(scala.collection.TraversableOnce coll) { scala.compat.java8.collectionImpl.DoubleAccumulator acc = scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.TraversableOnce)coll); return StreamSupport.doubleStream(acc.spliterator(), false); @@ -437,7 +437,7 @@ public static DoubleStream doubleFromAccumulated(scala.collection.TraversableOnc * @param coll The map containing keys to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static DoubleStream doubleFromAccumulatedKeys(scala.collection.Map coll) { + public static DoubleStream doubleStreamAccumulatedKeys(scala.collection.Map coll) { scala.compat.java8.collectionImpl.DoubleAccumulator acc = scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.keysIterator()); return StreamSupport.doubleStream(acc.spliterator(), false); @@ -452,7 +452,7 @@ public static DoubleStream doubleFromAccumulatedKeys(scala.collection.Map coll) { + public static DoubleStream doubleStreamAccumulatedValues(scala.collection.Map coll) { scala.compat.java8.collectionImpl.DoubleAccumulator acc = scala.compat.java8.collectionImpl.DoubleAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); return StreamSupport.doubleStream(acc.spliterator(), false); @@ -470,7 +470,7 @@ public static DoubleStream doubleFromAccumulatedValues(scala.collection.Map coll) { + public static IntStream intStream(scala.collection.IndexedSeq coll) { return StreamSupport.intStream(new StepsIntIndexedSeq(coll, 0, coll.length()), false); } @@ -509,7 +509,7 @@ public static IntStream intFrom(scala.collection.IndexedSeq coll) { * @param coll The immutable.HashMap to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromKeys(scala.collection.immutable.HashMap coll) { + public static IntStream intStreamKeys(scala.collection.immutable.HashMap coll) { return StreamSupport.intStream(new StepsIntImmHashMapKey(coll, 0, coll.size()), false); } @@ -521,7 +521,7 @@ public static IntStream intFromKeys(scala.collection.immutable.HashMap coll) { + public static IntStream intStreamValues(scala.collection.immutable.HashMap coll) { return StreamSupport.intStream(new StepsIntImmHashMapValue(coll, 0, coll.size()), false); } @@ -533,7 +533,7 @@ public static IntStream intFromValues(scala.collection.immutable.HashMap coll) { + public static IntStream intStream(scala.collection.immutable.HashSet coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.intStream(new StepsIntImmHashSet(iter, coll.size()), false); } @@ -546,7 +546,7 @@ public static IntStream intFrom(scala.collection.immutable.HashSet coll * @param coll The mutable.HashMap to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromKeys(scala.collection.mutable.HashMap coll) { + public static IntStream intStreamKeys(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.intStream(new StepsIntHashTableKey(tbl, 0, tbl.length), false); } @@ -559,7 +559,7 @@ public static IntStream intFromKeys(scala.collection.mutable.HashMap * @param coll The mutable.HashMap to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromValues(scala.collection.mutable.HashMap coll) { + public static IntStream intStreamValues(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.intStream(new StepsIntDefaultHashTableValue(tbl, 0, tbl.length), false); } @@ -572,7 +572,7 @@ public static IntStream intFromValues(scala.collection.mutable.HashMap coll) { + public static IntStream intStream(scala.collection.mutable.HashSet coll) { Object[] tbl = CollectionInternals.getTable(coll); return StreamSupport.intStream(new StepsIntFlatHashTable(tbl, 0, tbl.length), false); } @@ -585,7 +585,7 @@ public static IntStream intFrom(scala.collection.mutable.HashSet coll) * @param coll The Vector to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFrom(scala.collection.immutable.Vector coll) { + public static IntStream intStream(scala.collection.immutable.Vector coll) { scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; return StreamSupport.intStream(new StepsIntVector(erased, 0, coll.length()), false); } @@ -594,13 +594,13 @@ public static IntStream intFrom(scala.collection.immutable.Vector coll) * Generates a IntStream that traverses the int-valued keys of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the intFromAccumulatedKeys method instead, but + * For efficient parallel operation, use the intStreamAccumulatedKeys method instead, but * note that this creates a new collection containing the Map's keys. * * @param coll The Map to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromKeys(scala.collection.Map coll) { + public static IntStream intStreamKeys(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); return StreamSupport.intStream(new StepsIntIterator(iter), false); } @@ -609,13 +609,13 @@ public static IntStream intFromKeys(scala.collection.Map coll) { * Generates a IntStream that traverses the int-valued values of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the intFromAccumulatedValues method instead, but + * For efficient parallel operation, use the intStreamAccumulatedValues method instead, but * note that this creates a new collection containing the Map's values. * * @param coll The Map to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromValues(scala.collection.Map coll) { + public static IntStream intStreamValues(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); return StreamSupport.intStream(new StepsIntIterator(iter), false); } @@ -624,13 +624,13 @@ public static IntStream intFromValues(scala.collection.Map coll) { * Generates a IntStream that traverses a int-valued scala.collection.Iterator. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the intFromAccumulated method instead, + * For efficient parallel operation, use the intStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterator. * * @param coll The scala.collection.Iterator to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFrom(scala.collection.Iterator coll) { + public static IntStream intStream(scala.collection.Iterator coll) { return StreamSupport.intStream(new StepsIntIterator((scala.collection.Iterator)coll), false); } @@ -638,13 +638,13 @@ public static IntStream intFrom(scala.collection.Iterator coll) { * Generates a IntStream that traverses a int-valued scala.collection.Iterable. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the intFromAccumulated method instead, + * For efficient parallel operation, use the intStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterable. * * @param coll The scala.collection.Iterable to traverse * @return A IntStream view of the collection which, by default, executes sequentially. */ - public static IntStream intFrom(scala.collection.Iterable coll) { + public static IntStream intStream(scala.collection.Iterable coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.intStream(new StepsIntIterator(iter), false); } @@ -658,7 +658,7 @@ public static IntStream intFrom(scala.collection.Iterable coll) { * @param coll The collection to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromAccumulated(scala.collection.TraversableOnce coll) { + public static IntStream intStreamAccumulated(scala.collection.TraversableOnce coll) { scala.compat.java8.collectionImpl.IntAccumulator acc = scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.TraversableOnce)coll); return StreamSupport.intStream(acc.spliterator(), false); @@ -673,7 +673,7 @@ public static IntStream intFromAccumulated(scala.collection.TraversableOnce coll) { + public static IntStream intStreamAccumulatedKeys(scala.collection.Map coll) { scala.compat.java8.collectionImpl.IntAccumulator acc = scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.keysIterator()); return StreamSupport.intStream(acc.spliterator(), false); @@ -688,7 +688,7 @@ public static IntStream intFromAccumulatedKeys(scala.collection.Map * @param coll The map containing values to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static IntStream intFromAccumulatedValues(scala.collection.Map coll) { + public static IntStream intStreamAccumulatedValues(scala.collection.Map coll) { scala.compat.java8.collectionImpl.IntAccumulator acc = scala.compat.java8.collectionImpl.IntAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); return StreamSupport.intStream(acc.spliterator(), false); @@ -706,7 +706,7 @@ public static IntStream intFromAccumulatedValues(scala.collection.Map coll) { + public static LongStream longStream(scala.collection.IndexedSeq coll) { return StreamSupport.longStream(new StepsLongIndexedSeq(coll, 0, coll.length()), false); } @@ -718,7 +718,7 @@ public static LongStream longFrom(scala.collection.IndexedSeq coll) { * @param coll The immutable.HashMap to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromKeys(scala.collection.immutable.HashMap coll) { + public static LongStream longStreamKeys(scala.collection.immutable.HashMap coll) { return StreamSupport.longStream(new StepsLongImmHashMapKey(coll, 0, coll.size()), false); } @@ -730,7 +730,7 @@ public static LongStream longFromKeys(scala.collection.immutable.HashMap coll) { + public static LongStream longStreamValues(scala.collection.immutable.HashMap coll) { return StreamSupport.longStream(new StepsLongImmHashMapValue(coll, 0, coll.size()), false); } @@ -742,7 +742,7 @@ public static LongStream longFromValues(scala.collection.immutable.HashMap coll) { + public static LongStream longStream(scala.collection.immutable.HashSet coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.longStream(new StepsLongImmHashSet(iter, coll.size()), false); } @@ -755,7 +755,7 @@ public static LongStream longFrom(scala.collection.immutable.HashSet coll) * @param coll The mutable.HashMap to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromKeys(scala.collection.mutable.HashMap coll) { + public static LongStream longStreamKeys(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.longStream(new StepsLongHashTableKey(tbl, 0, tbl.length), false); } @@ -768,7 +768,7 @@ public static LongStream longFromKeys(scala.collection.mutable.HashMap * @param coll The mutable.HashMap to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromValues(scala.collection.mutable.HashMap coll) { + public static LongStream longStreamValues(scala.collection.mutable.HashMap coll) { scala.collection.mutable.HashEntry[] tbl = CollectionInternals.getTable(coll); return StreamSupport.longStream(new StepsLongDefaultHashTableValue(tbl, 0, tbl.length), false); } @@ -781,7 +781,7 @@ public static LongStream longFromValues(scala.collection.mutable.HashMap coll) { + public static LongStream longStream(scala.collection.mutable.HashSet coll) { Object[] tbl = CollectionInternals.getTable(coll); return StreamSupport.longStream(new StepsLongFlatHashTable(tbl, 0, tbl.length), false); } @@ -794,7 +794,7 @@ public static LongStream longFrom(scala.collection.mutable.HashSet coll) { * @param coll The Vector to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFrom(scala.collection.immutable.Vector coll) { + public static LongStream longStream(scala.collection.immutable.Vector coll) { scala.collection.immutable.Vector erased = (scala.collection.immutable.Vector)coll; return StreamSupport.longStream(new StepsLongVector(erased, 0, coll.length()), false); } @@ -803,13 +803,13 @@ public static LongStream longFrom(scala.collection.immutable.Vector coll) * Generates a LongStream that traverses the long-valued keys of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the longFromAccumulatedKeys method instead, but + * For efficient parallel operation, use the longStreamAccumulatedKeys method instead, but * note that this creates a new collection containing the Map's keys. * * @param coll The Map to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromKeys(scala.collection.Map coll) { + public static LongStream longStreamKeys(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.keysIterator(); return StreamSupport.longStream(new StepsLongIterator(iter), false); } @@ -818,13 +818,13 @@ public static LongStream longFromKeys(scala.collection.Map coll) { * Generates a LongStream that traverses the long-valued values of a scala.collection.Map. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the longFromAccumulatedValues method instead, but + * For efficient parallel operation, use the longStreamAccumulatedValues method instead, but * note that this creates a new collection containing the Map's values. * * @param coll The Map to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromValues(scala.collection.Map coll) { + public static LongStream longStreamValues(scala.collection.Map coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.valuesIterator(); return StreamSupport.longStream(new StepsLongIterator(iter), false); } @@ -833,13 +833,13 @@ public static LongStream longFromValues(scala.collection.Map coll) { * Generates a LongStream that traverses a long-valued scala.collection.Iterator. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the longFromAccumulated method instead, + * For efficient parallel operation, use the longStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterator. * * @param coll The scala.collection.Iterator to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFrom(scala.collection.Iterator coll) { + public static LongStream longStream(scala.collection.Iterator coll) { return StreamSupport.longStream(new StepsLongIterator((scala.collection.Iterator)coll), false); } @@ -847,13 +847,13 @@ public static LongStream longFrom(scala.collection.Iterator coll) { * Generates a LongStream that traverses a long-valued scala.collection.Iterable. *

* Only sequential operations will be efficient. - * For efficient parallel operation, use the longFromAccumulated method instead, + * For efficient parallel operation, use the longStreamAccumulated method instead, * but note that this creates a copy of the contents of the Iterable. * * @param coll The scala.collection.Iterable to traverse * @return A LongStream view of the collection which, by default, executes sequentially. */ - public static LongStream longFrom(scala.collection.Iterable coll) { + public static LongStream longStream(scala.collection.Iterable coll) { scala.collection.Iterator iter = (scala.collection.Iterator)coll.iterator(); return StreamSupport.longStream(new StepsLongIterator(iter), false); } @@ -867,7 +867,7 @@ public static LongStream longFrom(scala.collection.Iterable coll) { * @param coll The collection to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromAccumulated(scala.collection.TraversableOnce coll) { + public static LongStream longStreamAccumulated(scala.collection.TraversableOnce coll) { scala.compat.java8.collectionImpl.LongAccumulator acc = scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.TraversableOnce)coll); return StreamSupport.longStream(acc.spliterator(), false); @@ -882,7 +882,7 @@ public static LongStream longFromAccumulated(scala.collection.TraversableOnce coll) { + public static LongStream longStreamAccumulatedKeys(scala.collection.Map coll) { scala.compat.java8.collectionImpl.LongAccumulator acc = scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.keysIterator()); return StreamSupport.longStream(acc.spliterator(), false); @@ -897,7 +897,7 @@ public static LongStream longFromAccumulatedKeys(scala.collection.Map c * @param coll The map containing values to traverse * @return A Stream view of the collection which, by default, executes sequentially. */ - public static LongStream longFromAccumulatedValues(scala.collection.Map coll) { + public static LongStream longStreamAccumulatedValues(scala.collection.Map coll) { scala.compat.java8.collectionImpl.LongAccumulator acc = scala.compat.java8.collectionImpl.LongAccumulator.from((scala.collection.Iterator)coll.valuesIterator()); return StreamSupport.longStream(acc.spliterator(), false); diff --git a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java index e34a4d1..da16655 100644 --- a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java +++ b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import scala.collection.mutable.ArrayBuffer; -import scala.compat.java8.ScalaStreaming; +import scala.compat.java8.ScalaStreamSupport; public class StreamConvertersExampleTest { @@ -14,7 +14,7 @@ public void MakeAndUseArrayBuffer() { ArrayBuffer ab = new ArrayBuffer(); ab.$plus$eq("salmon"); ab.$plus$eq("herring"); - assert( ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum() == 13 ); + assert( ScalaStreamSupport.stream(ab).mapToInt(x -> x.length()).sum() == 13 ); } } From bf420085d707c5c9401722e34bc10757b4aec7c4 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 31 Mar 2016 15:32:58 +0200 Subject: [PATCH 093/340] Remove import in CollectionInternals --- .../java/scala/compat/java8/runtime/CollectionInternals.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index ba6f6a6..6f8da89 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -1,6 +1,6 @@ package scala.compat.java8.runtime; -import scala.collection.immutable.*; // Don't rely on this! Refer to everything explicitly! +// No imports! All type names are fully qualified to avoid confusion! public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } From 32520ff484ecefa2c867e76870f24d8e290b20ec Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 31 Mar 2016 16:08:48 +0200 Subject: [PATCH 094/340] Add documentation to ScalaStreamSupport --- .../java/scala/compat/java8/ScalaStreamSupport.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java index 54d29d8..21af821 100644 --- a/src/main/java/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -5,6 +5,16 @@ import java.util.stream.*; import scala.compat.java8.runtime.CollectionInternals; +/** + * This class contains static utility methods for creating Java Streams from Scala Collections, similar + * to the methods in {@code java.util.stream.StreamSupport} for other Java types. It is intended for + * use from Java code. In Scala code, you can use the extension methods provided by + * {@code scala.compat.java8.StreamConverters} instead. + * + * Streams created from immutable Scala collections are also immutable. Mutable collections should + * not be modified concurrently. There are no guarantees for success or failure modes of existing + * streams in case of concurrent modifications. + */ public class ScalaStreamSupport { ///////////////////// // Generic Streams // From cfee33dc17545df900ab1567ce3255cab6865cdb Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 31 Mar 2016 17:04:34 +0200 Subject: [PATCH 095/340] Box existing primitive steppers in `Stepper.ofSpliterator` --- .../compat/java8/collectionImpl/Stepper.scala | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 7476ded..c40b7bd 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -239,6 +239,32 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true) } +object AnyStepper { + private[collectionImpl] class BoxedDoubleStepper(st: DoubleStepper) extends AnyStepper[Double] { + def hasNext(): Boolean = st.hasNext() + def next(): Double = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): AnyStepper[Double] = new BoxedDoubleStepper(st.substep()) + } + + private[collectionImpl] class BoxedIntStepper(st: IntStepper) extends AnyStepper[Int] { + def hasNext(): Boolean = st.hasNext() + def next(): Int = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): AnyStepper[Int] = new BoxedIntStepper(st.substep()) + } + + private[collectionImpl] class BoxedLongStepper(st: LongStepper) extends AnyStepper[Long] { + def hasNext(): Boolean = st.hasNext() + def next(): Long = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): AnyStepper[Long] = new BoxedLongStepper(st.substep()) + } +} + /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] { def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } @@ -512,6 +538,9 @@ object Stepper { /** Creates a `Stepper` over a generic `Spliterator`. */ def ofSpliterator[A](sp: Spliterator[A]): AnyStepper[A] = sp match { case as: AnyStepper[A] => as + case s: DoubleStepper => new AnyStepper.BoxedDoubleStepper(s).asInstanceOf[AnyStepper[A]] + case s: IntStepper => new AnyStepper.BoxedIntStepper(s).asInstanceOf[AnyStepper[A]] + case s: LongStepper => new AnyStepper.BoxedLongStepper(s).asInstanceOf[AnyStepper[A]] case _ => new OfSpliterator[A](sp) } From 2ffa4d72131ca5295d371f6fd0bdd4cf08009801 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Fri, 1 Apr 2016 19:59:49 +0200 Subject: [PATCH 096/340] Automatic widening of numeric types for primitive Streams The widening conversions follow the usual pattern. Float becomes Double, Byte/Char/Short become Int. Boolean and Unit are not widened. For Arrays, where the actual data is unboxed, widening is implemented through custom Stepper implementations, so you can get e.g. a native IntStepper for an Array[Byte]. The StreamConverters hierarchy is modified to prefer these widened primitive steppers, so that, for example, the `seqStream` extension method on an Array[Byte] returns an IntStream. Other collection types with a boxed representation also get the same widening conversions (so you can still benefit from the better performance of unboxed streams) but there are no implicitly available widening steppers. Only the Stream extension methods fall back to applying a widening stepper in order to produce a widening primitive stream. Widening narrow numeric types for streams is consistent with the Streams API in the JDK. For example, `CharSequence.chars` returns an `IntStream` instead of a `Stream[Character]`. --- .../scala/compat/java8/StreamConverters.scala | 88 ++++++++++++++++++- .../compat/java8/collectionImpl/Stepper.scala | 45 +++++++++- .../java8/converterImpl/StepsArray.scala | 48 +++++----- .../compat/java8/StepConvertersTest.scala | 17 ++++ .../compat/java8/StreamConvertersTest.scala | 13 +++ 5 files changed, 181 insertions(+), 30 deletions(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 2c6affc..badb07b 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -14,7 +14,8 @@ trait PrimitiveStreamUnboxer[A, S] { def apply(boxed: Stream[A]): S } -trait Priority3StreamConverters { +trait Priority4StreamConverters { + // Fallback converters for AnySteppers that cannot be unboxed and widened to primitive streams implicit class EnrichAnySteppableWithParStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A] with EfficientSubstep]) extends MakesParallelStream[A, Stream[A]] { def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) @@ -25,7 +26,6 @@ trait Priority3StreamConverters { implicit class EnrichAnyValueSteppableWithParValueStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V] with EfficientSubstep]) { def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) } - // Note--conversion is only to make sure implicit conversion priority is lower than alternatives. implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A]]) extends MakesSequentialStream[A, Stream[A]] { def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) @@ -38,6 +38,90 @@ trait Priority3StreamConverters { } } +trait Priority3StreamConverters extends Priority4StreamConverters { + // Prefer to unbox and widen small primitive types over keeping them boxed + implicit class EnrichBoxedFloatSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Float] with EfficientSubstep]) + extends MakesParallelStream[java.lang.Double, DoubleStream] { + def parStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).stepper.anticipateParallelism), true) + } + implicit class EnrichBoxedFloatKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Float] with EfficientSubstep]) { + def parKeyStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).keyStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedFloatValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Float] with EfficientSubstep]) { + def parValueStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).valueStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedByteSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Byte] with EfficientSubstep]) + extends MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).stepper.anticipateParallelism), true) + } + implicit class EnrichBoxedByteKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Byte] with EfficientSubstep]) { + def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).keyStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedByteValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Byte] with EfficientSubstep]) { + def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).valueStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedShortSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Short] with EfficientSubstep]) + extends MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).stepper.anticipateParallelism), true) + } + implicit class EnrichBoxedShortKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Short] with EfficientSubstep]) { + def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).keyStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedShortValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Short] with EfficientSubstep]) { + def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).valueStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedCharSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Char] with EfficientSubstep]) + extends MakesParallelStream[java.lang.Integer, IntStream] { + def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).stepper.anticipateParallelism), true) + } + implicit class EnrichBoxedCharKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Char] with EfficientSubstep]) { + def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).keyStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedCharValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Char] with EfficientSubstep]) { + def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).valueStepper.anticipateParallelism), true) + } + implicit class EnrichBoxedFloatSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Float]]) + extends MakesSequentialStream[java.lang.Double, DoubleStream] { + def seqStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).stepper), false) + } + implicit class EnrichBoxedFloatKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Float]]) { + def seqKeyStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).keyStepper), false) + } + implicit class EnrichBoxedFloatValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Float]]) { + def seqValueStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).valueStepper), false) + } + implicit class EnrichBoxedByteSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Byte]]) + extends MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).stepper), false) + } + implicit class EnrichBoxedByteKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Byte]]) { + def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).keyStepper), false) + } + implicit class EnrichBoxedByteValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Byte]]) { + def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).valueStepper), false) + } + implicit class EnrichBoxedShortSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Short]]) + extends MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).stepper), false) + } + implicit class EnrichBoxedShortKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Short]]) { + def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).keyStepper), false) + } + implicit class EnrichBoxedShortValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Short]]) { + def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).valueStepper), false) + } + implicit class EnrichBoxedCharSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Char]]) + extends MakesSequentialStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).stepper), false) + } + implicit class EnrichBoxedCharKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Char]]) { + def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).keyStepper), false) + } + implicit class EnrichBoxedCharValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Char]]) { + def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).valueStepper), false) + } +} + trait Priority2StreamConverters extends Priority3StreamConverters { implicit class EnrichDoubleSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper with EfficientSubstep]) extends MakesParallelStream[java.lang.Double, DoubleStream] { diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index c40b7bd..e315024 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -239,8 +239,8 @@ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterat def parStream: java.util.stream.Stream[A] = java.util.stream.StreamSupport.stream(this, true) } -object AnyStepper { - private[collectionImpl] class BoxedDoubleStepper(st: DoubleStepper) extends AnyStepper[Double] { +private[collectionImpl] object AnyStepper { + final class BoxedDoubleStepper(st: DoubleStepper) extends AnyStepper[Double] { def hasNext(): Boolean = st.hasNext() def next(): Double = st.next() def characteristics(): Int = st.characteristics() @@ -248,7 +248,7 @@ object AnyStepper { def substep(): AnyStepper[Double] = new BoxedDoubleStepper(st.substep()) } - private[collectionImpl] class BoxedIntStepper(st: IntStepper) extends AnyStepper[Int] { + final class BoxedIntStepper(st: IntStepper) extends AnyStepper[Int] { def hasNext(): Boolean = st.hasNext() def next(): Int = st.next() def characteristics(): Int = st.characteristics() @@ -256,7 +256,7 @@ object AnyStepper { def substep(): AnyStepper[Int] = new BoxedIntStepper(st.substep()) } - private[collectionImpl] class BoxedLongStepper(st: LongStepper) extends AnyStepper[Long] { + final class BoxedLongStepper(st: LongStepper) extends AnyStepper[Long] { def hasNext(): Boolean = st.hasNext() def next(): Long = st.next() def characteristics(): Int = st.characteristics() @@ -564,4 +564,41 @@ object Stepper { case _ => new OfLongSpliterator(sp) } + /* These adapter classes can wrap an AnyStepper of a small numeric type into the appropriately widened + * primitive Stepper type. This provides a basis for more efficient stream processing on unboxed values + * provided that the original source of the data is already boxed. In other cases the widening conversion + * should always be performed directly on the original unboxed values in a custom Stepper implementation + * (see for example StepsWidenedByteArray). */ + + private[java8] class WideningByteStepper(st: AnyStepper[Byte]) extends IntStepper { + def hasNext(): Boolean = st.hasNext() + def nextInt(): Int = st.next() + def characteristics(): Int = st.characteristics() | NonNull + def estimateSize(): Long = st.estimateSize() + def substep(): IntStepper = new WideningByteStepper(st.substep()) + } + + private[java8] class WideningCharStepper(st: AnyStepper[Char]) extends IntStepper { + def hasNext(): Boolean = st.hasNext() + def nextInt(): Int = st.next() + def characteristics(): Int = st.characteristics() | NonNull + def estimateSize(): Long = st.estimateSize() + def substep(): IntStepper = new WideningCharStepper(st.substep()) + } + + private[java8] class WideningShortStepper(st: AnyStepper[Short]) extends IntStepper { + def hasNext(): Boolean = st.hasNext() + def nextInt(): Int = st.next() + def characteristics(): Int = st.characteristics() | NonNull + def estimateSize(): Long = st.estimateSize() + def substep(): IntStepper = new WideningShortStepper(st.substep()) + } + + private[java8] class WideningFloatStepper(st: AnyStepper[Float]) extends DoubleStepper { + def hasNext(): Boolean = st.hasNext() + def nextDouble(): Double = st.next() + def characteristics(): Int = st.characteristics() | NonNull + def estimateSize(): Long = st.estimateSize() + def substep(): DoubleStepper = new WideningFloatStepper(st.substep()) + } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index e4f6f01..8a960d0 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -35,28 +35,28 @@ extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { def semiclone(half: Int) = new StepsBoxedBooleanArray(underlying, i0, half) } -private[java8] class StepsBoxedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Byte, StepsBoxedByteArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedByteArray(underlying, i0, half) +private[java8] class StepsWidenedByteArray(underlying: Array[Byte], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsWidenedByteArray](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsWidenedByteArray(underlying, i0, half) } -private[java8] class StepsBoxedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Char, StepsBoxedCharArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedCharArray(underlying, i0, half) +private[java8] class StepsWidenedCharArray(underlying: Array[Char], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsWidenedCharArray](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsWidenedCharArray(underlying, i0, half) } -private[java8] class StepsBoxedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Short, StepsBoxedShortArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedShortArray(underlying, i0, half) +private[java8] class StepsWidenedShortArray(underlying: Array[Short], _i0: Int, _iN: Int) +extends StepsIntLikeIndexed[StepsWidenedShortArray](_i0, _iN) { + def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsWidenedShortArray(underlying, i0, half) } -private[java8] class StepsBoxedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Float, StepsBoxedFloatArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsBoxedFloatArray(underlying, i0, half) +private[java8] class StepsWidenedFloatArray(underlying: Array[Float], _i0: Int, _iN: Int) +extends StepsDoubleLikeIndexed[StepsWidenedFloatArray](_i0, _iN) { + def nextDouble() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE + def semiclone(half: Int) = new StepsWidenedFloatArray(underlying, i0, half) } private[java8] class StepsDoubleArray(underlying: Array[Double], _i0: Int, _iN: Int) @@ -97,20 +97,20 @@ final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) exte @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) } -final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesStepper[AnyStepper[Byte] with EfficientSubstep] { - @inline def stepper: AnyStepper[Byte] with EfficientSubstep = new StepsBoxedByteArray(underlying, 0, underlying.length) +final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { + @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedByteArray(underlying, 0, underlying.length) } -final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesStepper[AnyStepper[Char] with EfficientSubstep] { - @inline def stepper: AnyStepper[Char] with EfficientSubstep = new StepsBoxedCharArray(underlying, 0, underlying.length) +final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { + @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedCharArray(underlying, 0, underlying.length) } -final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesStepper[AnyStepper[Short] with EfficientSubstep] { - @inline def stepper: AnyStepper[Short] with EfficientSubstep = new StepsBoxedShortArray(underlying, 0, underlying.length) +final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { + @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedShortArray(underlying, 0, underlying.length) } -final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesStepper[AnyStepper[Float] with EfficientSubstep] { - @inline def stepper: AnyStepper[Float] with EfficientSubstep = new StepsBoxedFloatArray(underlying, 0, underlying.length) +final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { + @inline def stepper: DoubleStepper with EfficientSubstep = new StepsWidenedFloatArray(underlying, 0, underlying.length) } final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 2f09927..c4597d5 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -437,6 +437,23 @@ class StepConvertersTest { Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) } + @Test + def shortWidening() { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + + good( Array[Short](654321.toShort).stepper ) + + //TODO: None of these currently work because there are no native Stepper implementations. This does not only + // affect widening conversions though. While you can get, for example, an IntStepper for a WrappedArray[Int], + // all values have to go through a boxing/unboxing step! + + //good( ci.NumericRange(123456.toShort, 123458.toShort, 1.toShort).stepper ) + //good( ((Array[Short](654321.toShort): cm.WrappedArray[Short]): cm.ArrayLike[Short, cm.WrappedArray[Short]]).stepper ) + //good( (Array[Short](654321.toShort): cm.ArrayOps[Short]).stepper ) + //good( cm.ResizableArray[Short](654321.toShort).stepper ) + //good( (Array[Short](654321.toShort): cm.WrappedArray[Short]).stepper ) + } + @Test def comprehensivelyLong() { implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index b1ad2f5..7ce1340 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -234,4 +234,17 @@ class StreamConvertersTest { assert(hsL.parStream.isInstanceOf[LongStream]) } } + + @Test + def primitiveStreamTypes(): Unit = { + // Unboxed native + widening Steppers available: + assertEquals(Vector[Int](1, 2, 3), (Array[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Array[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[String]("a", "b"), (Array[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) + + // Boxed collections, widening via boxed AnySteppers: + assertEquals(Vector[Int](1, 2, 3), (Vector[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Vector[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[String]("a", "b"), (Vector[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) + } } From f029ed563d38338e4b9a3990f4025e23bb338738 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 6 Apr 2016 15:24:16 +0200 Subject: [PATCH 097/340] Improve README Explaining widening conversions, fixing errors, and clarifying the role of Steppers in the API. --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 54fe1b1..e6caf3f 100644 --- a/README.md +++ b/README.md @@ -121,22 +121,27 @@ class Test { Scala collections gain `seqStream` and `parStream` as extension methods that produce a Java 8 Stream running sequentially or in parallel, respectively. These are automatically specialized to a primitive -type if possible. For instance, `List(1,2).seqStream` produces an `IntStream`. Maps additionally have +type if possible, including automatically applied widening conversions. For instance, `List(1,2).seqStream` +produces an `IntStream`, and so does `List(1.toShort, 2.toShort).parStream`. Maps additionally have `seqKeyStream`, `seqValueStream`, `parKeyStream`, and `parValueStream` methods. Scala collections also gain `accumulate` and `stepper` methods that produce utility collections that can be useful when working with Java 8 Streams. `accumulate` produces an `Accumulator` or its primitive counterpart (`DoubleAccumulator`, etc.), which is a low-level collection designed for efficient collection and dispatching of results to and from Streams. Unlike most collections, it can contain more than -`Int.MaxValue` elements. `stepper` produces a `Stepper` which is a fusion of `Spliterator` and `Iterator`. -`Stepper`s underlie the Scala collections' instances of Java 8 Streams. +`Int.MaxValue` elements. + +`stepper` produces a `Stepper` which is a fusion of `Spliterator` and `Iterator`. `Stepper`s underlie the Scala +collections' instances of Java 8 Streams. Steppers are intended as low-level building blocks for streams. +Usually you would not create them directly or call their methods but you can implement them alongside custom +collections to get better performance when streaming from these collections. Java 8 Streams gain `toScala[Coll]` and `accumulate` methods, to make it easy to produce Scala collections or Accumulators, respectively, from Java 8 Streams. For instance, `myStream.to[Vector]` will collect the contents of a Stream into a `scala.collection.immutable.Vector`. Note that standard sequential builders are used for collections, so this is best done to gather the results of an expensive computation. -Finally, there is a Java class, `ScalaStreamer`, that has a series of `from` methods that can be used to +Finally, there is a Java class, `ScalaStreamSupport`, that has a series of `stream` methods that can be used to obtain Java 8 Streams from Scala collections from within Java. #### Performance Considerations @@ -218,7 +223,7 @@ def mapToSortedString[A](xs: Vector[A], f: A => String, sep: String) = #### Java Usage Example To convert a Scala collection to a Java 8 Stream from within Java, it usually -suffices to call `ScalaStreaming.from(xs)` on your collection `xs`. If `xs` is +suffices to call `ScalaStreamSupport.stream(xs)` on your collection `xs`. If `xs` is a map, you may wish to get the keys or values alone by using `fromKeys` or `fromValues`. If the collection has an underlying representation that is not efficiently parallelized (e.g. `scala.collection.immutable.List`), then @@ -237,14 +242,14 @@ Here is an example of conversion of a Scala collection within Java 8: ```java import scala.collection.mutable.ArrayBuffer; -import scala.compat.java8.ScalaStreaming; +import scala.compat.java8.ScalaStreamSupport; public class StreamConvertersExample { public int MakeAndUseArrayBuffer() { ArrayBuffer ab = new ArrayBuffer(); ab.$plus$eq("salmon"); ab.$plus$eq("herring"); - return ScalaStreaming.from(ab).mapToInt(x -> x.length()).sum(); // 6+7 = 13 + return ScalaStreamSupport.stream(ab).mapToInt(x -> x.length()).sum(); // 6+7 = 13 } } ``` From 55df152d044be03cd528790695f98991e5e85771 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 6 Apr 2016 21:45:46 +0200 Subject: [PATCH 098/340] Add support for Scala 2.12.0-M4 - M4 has native support for the `JFunction` types that used to be in this project but they are in `scala.runtime.java8`, not `scala.compat.java8`, so we move them to the same location. This breaks compatibility with the previous release of scala-java8-compat but now allows cross-building between Scala 2.11 and 2.12.0-M4. Tests and test support code is also moved to the new package. When building on 2.11 we still generate our own JFunctions but on 2.12 the native ones are used. - JFunctions in 2.12.0-M4 are not `Serializable` (see https://github.com/scala/scala-dev/issues/129) so the test for that is disabled for the time being. - There is currently no genjavadoc-plugin for M4, so we only build the docs on 2.11. --- .travis.yml | 4 +-- admin/build.sh | 6 ++++- build.sbt | 26 ++++++++++--------- project/CodeGen.scala | 2 +- .../scala/compat/java8/SpecializedTest.scala | 2 +- .../{compat => runtime}/java8/BoxingTest.java | 2 +- .../{compat => runtime}/java8/LambdaTest.java | 17 +++++++----- .../java8/SpecializedFactoryTest.java | 2 +- .../java8/SpecializedTestSupport.java | 2 +- 9 files changed, 36 insertions(+), 27 deletions(-) rename src/test/java/scala/{compat => runtime}/java8/BoxingTest.java (96%) rename src/test/java/scala/{compat => runtime}/java8/LambdaTest.java (90%) rename src/test/java/scala/{compat => runtime}/java8/SpecializedFactoryTest.java (95%) rename src/test/java/scala/{compat => runtime}/java8/SpecializedTestSupport.java (95%) diff --git a/.travis.yml b/.travis.yml index a7d0599..b73bc89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,8 +12,8 @@ env: script: - admin/build.sh scala: - - 2.11.7 - - 2.12.0-M3 + - 2.11.8 + - 2.12.0-M4 jdk: - oraclejdk8 notifications: diff --git a/admin/build.sh b/admin/build.sh index b67abcf..6e53ef7 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -22,4 +22,8 @@ if [ "$TRAVIS_JDK_VERSION" == "$PUBLISH_JDK" ] && [[ "$TRAVIS_TAG" =~ ^v[0-9]+\. openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d fi -sbt ++$TRAVIS_SCALA_VERSION "$publishVersion" clean update test publishLocal $extraTarget +if [ "$TRAVIS_SCALA_VERSION" == "2.12.0-M4" ]; then + extraSbtOpts="-Dnodocs=true" +fi + +sbt $extraSbtOpts ++$TRAVIS_SCALA_VERSION "$publishVersion" clean update test publishLocal $extraTarget diff --git a/build.sbt b/build.sbt index 9c0d927..c618551 100644 --- a/build.sbt +++ b/build.sbt @@ -3,16 +3,16 @@ val disableDocs = sys.props("nodocs") == "true" lazy val JavaDoc = config("genjavadoc") extend Compile def jwrite(dir: java.io.File)(name: String, content: String) = { - val f = dir / "scala" / "compat" / "java8" / s"${name}.java" + val f = dir / "scala" / "runtime" / "java8" / s"${name}.java" IO.write(f, content) f } lazy val commonSettings = Seq( - scalaVersion := "2.11.7", - crossScalaVersions := List("2.11.7", "2.12.0-M3"), + scalaVersion := "2.11.8", + crossScalaVersions := List("2.11.8", "2.12.0-M4"), organization := "org.scala-lang.modules", - version := "0.6.0-SNAPSHOT" + version := "0.8.0-SNAPSHOT" ) lazy val fnGen = (project in file("fnGen")). @@ -61,14 +61,16 @@ lazy val root = (project in file(".")). (out ** "*.scala").get }.taskValue, - sourceGenerators in Compile <+= sourceManaged in Compile map { dir => - val write = jwrite(dir) _ - Seq(write("JFunction", CodeGen.factory)) ++ - (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ - (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ - CodeGen.specializedF0.map(write.tupled) ++ - CodeGen.specializedF1.map(write.tupled) ++ - CodeGen.specializedF2.map(write.tupled) + sourceGenerators in Compile <+= (sourceManaged in Compile, scalaVersion) map { (dir, v) => + if(v.startsWith("2.11.")) { + val write = jwrite(dir) _ + Seq(write("JFunction", CodeGen.factory)) ++ + (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ + (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ + CodeGen.specializedF0.map(write.tupled) ++ + CodeGen.specializedF1.map(write.tupled) ++ + CodeGen.specializedF2.map(write.tupled) + } else Seq.empty }, sourceGenerators in Test <+= sourceManaged in Test map { dir => diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 68232e6..15c475f 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -25,7 +25,7 @@ object Type { } object CodeGen { - def packaging = "package scala.compat.java8;" + def packaging = "package scala.runtime.java8;" case class arity(n: Int) { val ns = (1 to n).toList diff --git a/src/test/java/scala/compat/java8/SpecializedTest.scala b/src/test/java/scala/compat/java8/SpecializedTest.scala index 564ef76..707ad82 100644 --- a/src/test/java/scala/compat/java8/SpecializedTest.scala +++ b/src/test/java/scala/compat/java8/SpecializedTest.scala @@ -4,7 +4,7 @@ package scala.compat.java8 import org.junit.Test -import scala.compat.java8.SpecializedTestSupport.IntIdentity +import scala.runtime.java8.SpecializedTestSupport.IntIdentity class SpecializedTest { @Test def specializationWorks() { diff --git a/src/test/java/scala/compat/java8/BoxingTest.java b/src/test/java/scala/runtime/java8/BoxingTest.java similarity index 96% rename from src/test/java/scala/compat/java8/BoxingTest.java rename to src/test/java/scala/runtime/java8/BoxingTest.java index 7074882..f4e6da6 100644 --- a/src/test/java/scala/compat/java8/BoxingTest.java +++ b/src/test/java/scala/runtime/java8/BoxingTest.java @@ -1,7 +1,7 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.compat.java8; +package scala.runtime.java8; import org.junit.Test; diff --git a/src/test/java/scala/compat/java8/LambdaTest.java b/src/test/java/scala/runtime/java8/LambdaTest.java similarity index 90% rename from src/test/java/scala/compat/java8/LambdaTest.java rename to src/test/java/scala/runtime/java8/LambdaTest.java index 84a586d..7d9f7b7 100644 --- a/src/test/java/scala/compat/java8/LambdaTest.java +++ b/src/test/java/scala/runtime/java8/LambdaTest.java @@ -1,14 +1,14 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.compat.java8; +package scala.runtime.java8; import org.apache.commons.lang3.SerializationUtils; import scala.runtime.*; import static junit.framework.Assert.assertEquals; -import static scala.compat.java8.JFunction.*; -import static scala.compat.java8.TestAPI.*; +import static scala.runtime.java8.JFunction.*; +import static scala.runtime.java8.TestAPI.*; import org.junit.Test; @@ -99,20 +99,23 @@ public void lambdaDemo() { acceptFunction22Unit( proc((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return;})); } + /* + // The JFunctions in 2.12.0-M4 are not Serializable anymore @Test public void isSerializable() { - scala.compat.java8.JFunction0 f0 = () -> "foo"; + scala.runtime.java8.JFunction0 f0 = () -> "foo"; assertEquals("foo", SerializationUtils.clone(f0).apply()); - scala.compat.java8.JFunction1 f1 = (a) -> a.toUpperCase(); + scala.runtime.java8.JFunction1 f1 = (a) -> a.toUpperCase(); assertEquals("FOO", SerializationUtils.clone(f1).apply("foo")); - scala.compat.java8.JFunction2 f2 = (a, b) -> a + b; + scala.runtime.java8.JFunction2 f2 = (a, b) -> a + b; assertEquals("foobar", SerializationUtils.clone(f2).apply("foo", "bar")); - scala.compat.java8.JFunction3 f3 = (a, b, c) -> a + b + c; + scala.runtime.java8.JFunction3 f3 = (a, b, c) -> a + b + c; assertEquals("foobarbaz", SerializationUtils.clone(f3).apply("foo", "bar", "baz")); } + */ private static scala.concurrent.Future futureExample( scala.concurrent.Future future, scala.concurrent.ExecutionContext ec) { diff --git a/src/test/java/scala/compat/java8/SpecializedFactoryTest.java b/src/test/java/scala/runtime/java8/SpecializedFactoryTest.java similarity index 95% rename from src/test/java/scala/compat/java8/SpecializedFactoryTest.java rename to src/test/java/scala/runtime/java8/SpecializedFactoryTest.java index 2e83412..bd4dddb 100644 --- a/src/test/java/scala/compat/java8/SpecializedFactoryTest.java +++ b/src/test/java/scala/runtime/java8/SpecializedFactoryTest.java @@ -1,7 +1,7 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.compat.java8; +package scala.runtime.java8; import org.junit.Test; import scala.runtime.BoxedUnit; diff --git a/src/test/java/scala/compat/java8/SpecializedTestSupport.java b/src/test/java/scala/runtime/java8/SpecializedTestSupport.java similarity index 95% rename from src/test/java/scala/compat/java8/SpecializedTestSupport.java rename to src/test/java/scala/runtime/java8/SpecializedTestSupport.java index 8309f26..2ba2833 100644 --- a/src/test/java/scala/compat/java8/SpecializedTestSupport.java +++ b/src/test/java/scala/runtime/java8/SpecializedTestSupport.java @@ -1,7 +1,7 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.compat.java8; +package scala.runtime.java8; import java.util.Arrays; import java.util.List; From 4c0c411a52de48ed30b431761f5b6a659c404241 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 7 Apr 2016 17:16:06 +0200 Subject: [PATCH 099/340] Make benchmarks work again and simplify benchmarking procedure --- .gitignore | 1 + benchmark/README.md | 6 ++-- benchmark/build.sbt | 11 +++++-- benchmark/project/plugins.sbt | 2 +- benchmark/src/main/scala/bench/CodeGen.scala | 8 +++++ .../main/scala/bench/CollectionSource.scala | 32 +++++++++---------- build.sbt | 2 +- 7 files changed, 37 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index 86fb982..41ed2bf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ target /.settings /.target /bin +benchmark/JmhBench.scala \ No newline at end of file diff --git a/benchmark/README.md b/benchmark/README.md index eb68ef9..c7d3491 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -6,11 +6,9 @@ Because the benchmarking is **very computationally expensive** it should be done ## Code generation step -1. Run `sbt console` - -2. If the `JmhBench.scala` file already exists, delete it. +1. Make sure the parent project has been built by running `sbt package` in it. -3. Enter `bench.codegen.Generate.jmhBench()` to generate the `JmhBench.scala` file. +2. `cd` to the benchmark project and run `sbt generateJmh` ## Benchmarking step diff --git a/benchmark/build.sbt b/benchmark/build.sbt index 5365275..5a7420f 100644 --- a/benchmark/build.sbt +++ b/benchmark/build.sbt @@ -1,10 +1,15 @@ enablePlugins(JmhPlugin) +val generateJmh = TaskKey[Unit]("generateJmh", "Generates JMH benchmark sources.") + lazy val root = (project in file(".")).settings( name := "java8-compat-bench", - scalaVersion := "2.11.7", - crossScalaVersions := List("2.11.7" /* TODO, "2.12.0-M3"*/), + scalaVersion := "2.11.8", + crossScalaVersions := List("2.11.8" /* TODO, "2.12.0-M4"*/), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", - unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.6.0-SNAPSHOT.jar") + unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.8.0-SNAPSHOT.jar"), + // This would be nicer but sbt-jmh doesn't like it: + //unmanagedClasspath in Compile += Attributed.blank(baseDirectory.value / "../target/scala-2.11/classes"), + generateJmh := (runMain in Compile).toTask(" bench.codegen.GenJmhBench").value ) diff --git a/benchmark/project/plugins.sbt b/benchmark/project/plugins.sbt index c5220d0..f5319fb 100644 --- a/benchmark/project/plugins.sbt +++ b/benchmark/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.5") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.6") diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 4e206ce..09a1af3 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -232,3 +232,11 @@ object Generator { } } } + +object GenJmhBench { + def main(args: Array[String]): Unit = { + val f = new java.io.File("JmhBench.scala") + f.delete() + Generator.jmhBench(f) + } +} diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 689aa42..5f40a33 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -25,30 +25,30 @@ package object generate { } object Pstep { - def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStepper = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]): IntStepper = steppize(cc).stepper - def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): AnyStepper[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String] with EfficientSubstep]): AnyStepper[String] = steppize(cc).stepper } object Sstep { - def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStepper = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]): IntStepper = steppize(cc).stepper - def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): AnyStepper[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String]]): AnyStepper[String] = steppize(cc).stepper } object PsStream { - def i[CC](cc: CC)(implicit steppize: CC => MakesIntStepper): IntStream = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]): IntStream = steppize(cc).stepper.parStream - def s[CC](cc: CC)(implicit steppize: CC => MakesAnyStepper[String]): Stream[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String] with EfficientSubstep]): Stream[String] = steppize(cc).stepper.parStream } object SsStream { - def i[CC](cc: CC)(implicit steppize: CC => MakesIntSeqStepper): IntStream = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]): IntStream = steppize(cc).stepper.seqStream - def s[CC](cc: CC)(implicit steppize: CC => MakesAnySeqStepper[String]): Stream[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String]]): Stream[String] = steppize(cc).stepper.seqStream } @@ -78,14 +78,14 @@ package object generate { // Iterator def iI(j: Int)(implicit x: CC[Int] => Iterator[Int]) = x(cI(j)) // Steppers (second letter--s = sequential, p = parallel) - def tsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = Sstep i cI(j) - def tpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = Pstep i cI(j) + def tsI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper]) = Sstep i cI(j) + def tpI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper with EfficientSubstep]) = Pstep i cI(j) // Streams def ssI(j: Int)(implicit x: CC[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = Sstream i cI(j) def spI(j: Int)(implicit x: CC[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = Pstream i cI(j) // Streams via steppers - def zsI(j: Int)(implicit x: CC[Int] => MakesIntSeqStepper) = SsStream i cI(j) - def zpI(j: Int)(implicit x: CC[Int] => MakesIntStepper) = PsStream i cI(j) + def zsI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper]) = SsStream i cI(j) + def zpI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper with EfficientSubstep]) = PsStream i cI(j) } trait StringThingsOf[CC[_]] extends GenThingsOf[CC] { @@ -95,14 +95,14 @@ package object generate { // Iterator def iS(j: Int)(implicit x: CC[String] => Iterator[String]) = x(cS(j)) // Steppers (second letter--s = sequential, p = parallel) - def tsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = Sstep s cS(j) - def tpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = Pstep s cS(j) + def tsS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String]]) = Sstep s cS(j) + def tpS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String] with EfficientSubstep]) = Pstep s cS(j) // Streams def ssS(j: Int)(implicit x: CC[String] => MakesSequentialStream[String, Stream[String]]) = Sstream s cS(j) def spS(j: Int)(implicit x: CC[String] => MakesParallelStream[String, Stream[String]]) = Pstream s cS(j) // Streams via steppers - def zsS(j: Int)(implicit x: CC[String] => MakesAnySeqStepper[String]) = SsStream s cS(j) - def zpS(j: Int)(implicit x: CC[String] => MakesAnyStepper[String]) = PsStream s cS(j) + def zsS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String]]) = SsStream s cS(j) + def zpS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String] with EfficientSubstep]) = PsStream s cS(j) } trait ThingsOf[CC[_]] extends IntThingsOf[CC] with StringThingsOf[CC] {} diff --git a/build.sbt b/build.sbt index 9c0d927..c2da864 100644 --- a/build.sbt +++ b/build.sbt @@ -109,6 +109,6 @@ lazy val root = (project in file(".")). """|import scala.concurrent._ |import ExecutionContext.Implicits.global |import java.util.concurrent.{CompletionStage,CompletableFuture} - |import scala.compat.java8.FutureConverter._ + |import scala.compat.java8.FutureConverters._ |""".stripMargin ) From dd965bb0ace52027464bad6455f5368b3187a650 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Fri, 8 Apr 2016 17:04:49 +0200 Subject: [PATCH 100/340] Re-enable genjavadoc on 2.12.0-M4 --- admin/build.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/admin/build.sh b/admin/build.sh index 6e53ef7..b67abcf 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -22,8 +22,4 @@ if [ "$TRAVIS_JDK_VERSION" == "$PUBLISH_JDK" ] && [[ "$TRAVIS_TAG" =~ ^v[0-9]+\. openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d fi -if [ "$TRAVIS_SCALA_VERSION" == "2.12.0-M4" ]; then - extraSbtOpts="-Dnodocs=true" -fi - -sbt $extraSbtOpts ++$TRAVIS_SCALA_VERSION "$publishVersion" clean update test publishLocal $extraTarget +sbt ++$TRAVIS_SCALA_VERSION "$publishVersion" clean update test publishLocal $extraTarget From 9dd46f387a5ef39ec7fc861d29c5c89fbcbcaf4d Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 13 Apr 2016 20:15:53 +0200 Subject: [PATCH 101/340] Unboxed Steppers for `WrappedArray` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `WrappedArray` now produces the same primitive, non-boxing `Stepper` that the underlying `Array` would. - Plus some improvements to the unit tests and benchmarks. An interesting observation from the benchmarks: `IntStream.sum` is horribly slow when used on a seqStream built from an `IntStepper`. It is still slow when used on a seqStream built directly from an `Array` with Java’s own stream support. Using a `while` loop on an `IntIterator` produced by the stream beats both hands down and has the same performance independent of the stream source. --- benchmark/README.md | 14 ++--- benchmark/build.sbt | 4 +- .../src/main/scala/bench/Operations.scala | 8 ++- .../src/main/scala/bench/ParseJmhLog.scala | 2 + .../java8/converterImpl/StepConverters.scala | 13 ++++- .../compat/java8/StepConvertersTest.scala | 56 ++++++++++--------- .../compat/java8/StreamConvertersTest.scala | 18 +++++- 7 files changed, 75 insertions(+), 40 deletions(-) diff --git a/benchmark/README.md b/benchmark/README.md index c7d3491..2d6e4e9 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -14,18 +14,14 @@ Because the benchmarking is **very computationally expensive** it should be done 1. Make sure your terminal has plenty of lines of scrollback. (A couple thousand should do.) -2. Run `sbt` +2. Run `sbt "jmh:run -i 5 -wi 3 -f 5"`. Wait overnight. -3. Enter `jmh:run -i 5 -wi 3 -f5`. Wait overnight. +3. Clip off the last set of lines from the terminal window starting before the line that contains `[info] # Run complete. Total time:` and including that line until the end. -4. Clip off the last set of lines from the terminal window starting before the line that contains `[info] # Run complete. Total time:` and including that line until the end. - -5. Save that in the file `results/jmhbench.log` +4. Save that in the file `results/jmhbench.log` ## Comparison step -1. Run `sbt console` - -2. Enter `bench.examine.SpeedReports()` +1. Run `sbt parseJmh` -3. Look at the ASCII art results showing speed comparisons. +2. Look at the ASCII art results showing speed comparisons. diff --git a/benchmark/build.sbt b/benchmark/build.sbt index 5a7420f..8aa4d2b 100644 --- a/benchmark/build.sbt +++ b/benchmark/build.sbt @@ -1,6 +1,7 @@ enablePlugins(JmhPlugin) val generateJmh = TaskKey[Unit]("generateJmh", "Generates JMH benchmark sources.") +val parseJmh = TaskKey[Unit]("parseJmh", "Parses JMH benchmark logs in results/jmhbench.log.") lazy val root = (project in file(".")).settings( name := "java8-compat-bench", @@ -11,5 +12,6 @@ lazy val root = (project in file(".")).settings( unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.8.0-SNAPSHOT.jar"), // This would be nicer but sbt-jmh doesn't like it: //unmanagedClasspath in Compile += Attributed.blank(baseDirectory.value / "../target/scala-2.11/classes"), - generateJmh := (runMain in Compile).toTask(" bench.codegen.GenJmhBench").value + generateJmh := (runMain in Compile).toTask(" bench.codegen.GenJmhBench").value, + parseJmh := (runMain in Compile).toTask(" bench.examine.ParseJmhLog").value ) diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala index 6208ac4..0b795db 100644 --- a/benchmark/src/main/scala/bench/Operations.scala +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -27,7 +27,13 @@ object OnInt { def sum(t: Traversable[Int]): Int = t.sum def sum(i: Iterator[Int]): Int = i.sum def sum(s: IntStepper): Int = s.fold(0)(_ + _) - def sum(s: IntStream): Int = s.sum + def sum(s: IntStream): Int = { + s.sum + /*var r = 0 + val it = s.iterator() + while(it.hasNext) r += it.nextInt() + r*/ + } def psum(i: ParIterable[Int]): Int = i.sum def psum(s: IntStream): Int = s.sum diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala index df45ee9..32d110a 100644 --- a/benchmark/src/main/scala/bench/ParseJmhLog.scala +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -143,4 +143,6 @@ object ParseJmhLog { println("-"*79) println } + + def main(args: Array[String]): Unit = apply() } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala index 1269f94..f27900f 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala @@ -84,6 +84,13 @@ trait Priority2StepConverters extends Priority3StepConverters { implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) + + // No special cases for AnyStepper-producing WrappedArrays; they are treated as IndexedSeqs + implicit def richWrappedArrayByteCanStep(underlying: collection.mutable.WrappedArray[Byte]) = new RichArrayByteCanStep(underlying.array) + implicit def richWrappedArrayCharCanStep(underlying: collection.mutable.WrappedArray[Char]) = new RichArrayCharCanStep(underlying.array) + implicit def richWrappedArrayShortCanStep(underlying: collection.mutable.WrappedArray[Short]) = new RichArrayShortCanStep(underlying.array) + implicit def richWrappedArrayFloatCanStep(underlying: collection.mutable.WrappedArray[Float]) = new RichArrayFloatCanStep(underlying.array) + implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = new RichDoubleIndexedSeqCanStep[CC](underlying) implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = @@ -113,7 +120,11 @@ trait Priority1StepConverters extends Priority2StepConverters { implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - + + implicit def richWrappedArrayDoubleCanStep(underlying: collection.mutable.WrappedArray[Double]) = new RichArrayDoubleCanStep(underlying.array) + implicit def richWrappedArrayIntCanStep(underlying: collection.mutable.WrappedArray[Int]) = new RichArrayIntCanStep(underlying.array) + implicit def richWrappedArrayLongCanStep(underlying: collection.mutable.WrappedArray[Long]) = new RichArrayLongCanStep(underlying.array) + implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index c4597d5..d7efe82 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -25,46 +25,54 @@ class StepConvertersTest { case _ => false } - trait SpecCheck { def apply[X](x: X): Boolean } + trait SpecCheck { + def check[X](x: X): Boolean + def msg[X](x: X): String + def assert(x: Any): Unit = + if(!check(x)) assertTrue(msg(x), false) + } object SpecCheck { - def apply(f: Any => Boolean) = new SpecCheck { def apply[X](x: X): Boolean = f(x) } + def apply(f: Any => Boolean, err: Any => String = (_ => "SpecCheck failed")) = new SpecCheck { + def check[X](x: X): Boolean = f(x) + def msg[X](x: X): String = err(x) + } } def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) } def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) - assert(isAcc(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(isAcc(x)) } def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) - assert(!isAcc(x)) - assert(isLin(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) + assertTrue(isLin(x)) } def Fine[X](x: => X)(implicit correctSpec: SpecCheck) { - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) - assert(!isAcc(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) } def good[X](x: => X)(implicit correctSpec: SpecCheck) { - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) - assert(!isAcc(x)) - assert(!isLin(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) + assertTrue(!isLin(x)) } def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { println(x.getClass.getName + " -> " + isAcc(x)) - assert(x.isInstanceOf[Stepper[_]]) - assert(correctSpec(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) } @Test @@ -439,19 +447,17 @@ class StepConvertersTest { @Test def shortWidening() { - implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( Array[Short](654321.toShort).stepper ) + good( (Array[Short](654321.toShort): cm.WrappedArray[Short]).stepper ) - //TODO: None of these currently work because there are no native Stepper implementations. This does not only - // affect widening conversions though. While you can get, for example, an IntStepper for a WrappedArray[Int], - // all values have to go through a boxing/unboxing step! + //TODO: None of these currently work because there are no native Stepper implementations: //good( ci.NumericRange(123456.toShort, 123458.toShort, 1.toShort).stepper ) //good( ((Array[Short](654321.toShort): cm.WrappedArray[Short]): cm.ArrayLike[Short, cm.WrappedArray[Short]]).stepper ) //good( (Array[Short](654321.toShort): cm.ArrayOps[Short]).stepper ) //good( cm.ResizableArray[Short](654321.toShort).stepper ) - //good( (Array[Short](654321.toShort): cm.WrappedArray[Short]).stepper ) } @Test diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 7ce1340..44ca113 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -3,10 +3,13 @@ package scala.compat.java8 import org.junit.Test import org.junit.Assert._ +import java.util.stream._ +import StreamConverters._ +import scala.compat.java8.collectionImpl.IntStepper +import scala.compat.java8.converterImpl.{MakesStepper, MakesSequentialStream} + class StreamConvertersTest { - import java.util.stream._ - import StreamConverters._ - + def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } @@ -247,4 +250,13 @@ class StreamConvertersTest { assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Vector[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) assertEquals(Vector[String]("a", "b"), (Vector[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) } + + @Test + def streamMaterialization(): Unit = { + val coll = collection.mutable.WrappedArray.make[Int](Array(1,2,3)) + val streamize = implicitly[collection.mutable.WrappedArray[Int] => MakesSequentialStream[java.lang.Integer, IntStream]] + assertTrue(streamize(coll).getClass.getName.contains("EnrichScalaCollectionWithSeqIntStream")) + val steppize = implicitly[collection.mutable.WrappedArray[Int] => MakesStepper[IntStepper]] + assertTrue(steppize(coll).getClass.getName.contains("RichArrayIntCanStep")) + } } From c0221902ec7d321f6dbb66ee197f057fc974287c Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Thu, 14 Apr 2016 14:34:16 +0200 Subject: [PATCH 102/340] Special-case primitive `WrappedArray` types when creating Streams This was already done for `Array` in the same way. Streams produced by `Arrays.stream` can be faster than going through a `Stepper`. --- .../scala/compat/java8/StreamConverters.scala | 18 ++++++++++++++++++ .../compat/java8/StreamConvertersTest.scala | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index badb07b..394fc4c 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -292,6 +292,24 @@ with converterImpl.Priority1AccumulatorConverters def parStream: LongStream = seqStream.parallel } + implicit final class EnrichDoubleWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Double]) + extends AnyVal with MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { + def seqStream: DoubleStream = java.util.Arrays.stream(a.array) + def parStream: DoubleStream = seqStream.parallel + } + + implicit final class EnrichIntWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Int]) + extends AnyVal with MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { + def seqStream: IntStream = java.util.Arrays.stream(a.array) + def parStream: IntStream = seqStream.parallel + } + + implicit final class EnrichLongWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Long]) + extends AnyVal with MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { + def seqStream: LongStream = java.util.Arrays.stream(a.array) + def parStream: LongStream = seqStream.parallel + } + implicit val primitiveAccumulateDoubleStream = new PrimitiveStreamAccumulator[Stream[Double], DoubleAccumulator] { def streamAccumulate(stream: Stream[Double]): DoubleAccumulator = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 44ca113..66997bf 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -255,7 +255,7 @@ class StreamConvertersTest { def streamMaterialization(): Unit = { val coll = collection.mutable.WrappedArray.make[Int](Array(1,2,3)) val streamize = implicitly[collection.mutable.WrappedArray[Int] => MakesSequentialStream[java.lang.Integer, IntStream]] - assertTrue(streamize(coll).getClass.getName.contains("EnrichScalaCollectionWithSeqIntStream")) + assertTrue(streamize(coll).getClass.getName.contains("EnrichIntWrappedArrayWithStream")) val steppize = implicitly[collection.mutable.WrappedArray[Int] => MakesStepper[IntStepper]] assertTrue(steppize(coll).getClass.getName.contains("RichArrayIntCanStep")) } From 56e66b952b10965a0fcd87e4ac4e9372d682c65d Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 18 Apr 2016 18:26:43 +0200 Subject: [PATCH 103/340] A new approach to Stepper and Stream materialization Getting the most efficient Stepper implementation requires knowledge of the static type of a collection. This problem could be solved in the most elegant way by integrating Steppers into the collections framework as a replacement for Iterators (i.e. every collection gets a `stepper` method and `iterator` delegates to `stepper` by default). But this is at odds with the handling of specialized primitive Steppers in the current implementation. If we want `stepper` to be an instance methods instead of an extension method, there needs to be a single such method for all specialized Steppers. The fundamental change in this new implementation is to encode the translation from element type to Stepper type (including widening conversions) as a functional dependency via the new `StepperShape` trait. This greatly reduces the number of implicit methods and classes and keeps all specialized versions of `MakesStepper` together. The default base classes support all unboxing and widening conversions so that a simple `MakesStepper` for a collection of boxed elements only needs to handle the `AnyStepper` case. `keyStepper` and `valueStepper` are handled in the same way. `StreamConverters` use a separate `StreamShape` for the translation from element type to `BaseStream` subtype which is compatible with `StepConverters` and supports the same primitive types and widening conversions. --- .../main/scala/bench/CollectionSource.scala | 57 ++--- .../compat/java8/ScalaStreamSupport.java | 4 +- .../scala/compat/java8/StreamConverters.scala | 231 +++++------------- .../compat/java8/collectionImpl/Stepper.scala | 49 +++- .../java8/converterImpl/MakesSteppers.scala | 120 +++++++-- .../java8/converterImpl/StepConverters.scala | 126 +--------- .../java8/converterImpl/StepsArray.scala | 69 ++---- .../java8/converterImpl/StepsBitSet.scala | 7 +- .../converterImpl/StepsFlatHashTable.scala | 33 +-- .../java8/converterImpl/StepsHashTable.scala | 170 +++++-------- .../java8/converterImpl/StepsImmHashMap.scala | 49 ++-- .../java8/converterImpl/StepsImmHashSet.scala | 22 +- .../java8/converterImpl/StepsIndexedSeq.scala | 22 +- .../java8/converterImpl/StepsIterable.scala | 22 +- .../java8/converterImpl/StepsIterator.scala | 23 +- .../java8/converterImpl/StepsLinearSeq.scala | 62 +++-- .../compat/java8/converterImpl/StepsMap.scala | 42 ++-- .../java8/converterImpl/StepsRange.scala | 22 +- .../java8/converterImpl/StepsString.scala | 6 +- .../java8/converterImpl/StepsVector.scala | 22 +- .../compat/java8/StepConvertersTest.scala | 4 +- .../compat/java8/StreamConvertersTest.scala | 43 ++-- 22 files changed, 479 insertions(+), 726 deletions(-) diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 5f40a33..2713543 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -6,6 +6,7 @@ import scala.collection.generic.CanBuildFrom import scala.compat.java8.StreamConverters._ import scala.compat.java8.collectionImpl._ import scala.compat.java8.converterImpl._ +import scala.compat.java8.{MakesSequentialStream, MakesParallelStream} package object generate { private def myInty(n: Int) = 0 until n @@ -25,42 +26,42 @@ package object generate { } object Pstep { - def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]): IntStepper = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[Int, EfficientSubstep]): IntStepper = steppize(cc).stepper - def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String] with EfficientSubstep]): AnyStepper[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[String, EfficientSubstep]): AnyStepper[String] = steppize(cc).stepper } object Sstep { - def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]): IntStepper = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[Int, Any]): IntStepper = steppize(cc).stepper - def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String]]): AnyStepper[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[String, Any]): AnyStepper[String] = steppize(cc).stepper } object PsStream { - def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]): IntStream = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[Int, EfficientSubstep]): IntStream = steppize(cc).stepper.parStream - def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String] with EfficientSubstep]): Stream[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[String, EfficientSubstep]): Stream[String] = steppize(cc).stepper.parStream } object SsStream { - def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]): IntStream = + def i[CC](cc: CC)(implicit steppize: CC => MakesStepper[Int, Any]): IntStream = steppize(cc).stepper.seqStream - def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[String]]): Stream[String] = + def s[CC](cc: CC)(implicit steppize: CC => MakesStepper[String, Any]): Stream[String] = steppize(cc).stepper.seqStream } object Sstream { - def i[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[java.lang.Integer, IntStream]) = + def i[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[Int, IntStream]) = streamize(cc).seqStream def s[CC](cc: CC)(implicit streamize: CC => MakesSequentialStream[String, Stream[String]]) = streamize(cc).seqStream } object Pstream { - def i[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[java.lang.Integer, IntStream]) = + def i[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[Int, IntStream]) = streamize(cc).parStream def s[CC](cc: CC)(implicit streamize: CC => MakesParallelStream[String, Stream[String]]) = streamize(cc).parStream @@ -78,14 +79,14 @@ package object generate { // Iterator def iI(j: Int)(implicit x: CC[Int] => Iterator[Int]) = x(cI(j)) // Steppers (second letter--s = sequential, p = parallel) - def tsI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper]) = Sstep i cI(j) - def tpI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper with EfficientSubstep]) = Pstep i cI(j) + def tsI(j: Int)(implicit x: CC[Int] => MakesStepper[Int, Any]) = Sstep i cI(j) + def tpI(j: Int)(implicit x: CC[Int] => MakesStepper[Int, EfficientSubstep]) = Pstep i cI(j) // Streams - def ssI(j: Int)(implicit x: CC[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = Sstream i cI(j) - def spI(j: Int)(implicit x: CC[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = Pstream i cI(j) + def ssI(j: Int)(implicit x: CC[Int] => MakesSequentialStream[Int, IntStream]) = Sstream i cI(j) + def spI(j: Int)(implicit x: CC[Int] => MakesParallelStream[Int, IntStream]) = Pstream i cI(j) // Streams via steppers - def zsI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper]) = SsStream i cI(j) - def zpI(j: Int)(implicit x: CC[Int] => MakesStepper[IntStepper with EfficientSubstep]) = PsStream i cI(j) + def zsI(j: Int)(implicit x: CC[Int] => MakesStepper[Int, Any]) = SsStream i cI(j) + def zpI(j: Int)(implicit x: CC[Int] => MakesStepper[Int, EfficientSubstep]) = PsStream i cI(j) } trait StringThingsOf[CC[_]] extends GenThingsOf[CC] { @@ -95,14 +96,14 @@ package object generate { // Iterator def iS(j: Int)(implicit x: CC[String] => Iterator[String]) = x(cS(j)) // Steppers (second letter--s = sequential, p = parallel) - def tsS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String]]) = Sstep s cS(j) - def tpS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String] with EfficientSubstep]) = Pstep s cS(j) + def tsS(j: Int)(implicit x: CC[String] => MakesStepper[String, Any]) = Sstep s cS(j) + def tpS(j: Int)(implicit x: CC[String] => MakesStepper[String, EfficientSubstep]) = Pstep s cS(j) // Streams def ssS(j: Int)(implicit x: CC[String] => MakesSequentialStream[String, Stream[String]]) = Sstream s cS(j) def spS(j: Int)(implicit x: CC[String] => MakesParallelStream[String, Stream[String]]) = Pstream s cS(j) // Streams via steppers - def zsS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String]]) = SsStream s cS(j) - def zpS(j: Int)(implicit x: CC[String] => MakesStepper[AnyStepper[String] with EfficientSubstep]) = PsStream s cS(j) + def zsS(j: Int)(implicit x: CC[String] => MakesStepper[String, Any]) = SsStream s cS(j) + def zpS(j: Int)(implicit x: CC[String] => MakesStepper[String, EfficientSubstep]) = PsStream s cS(j) } trait ThingsOf[CC[_]] extends IntThingsOf[CC] with StringThingsOf[CC] {} @@ -158,16 +159,16 @@ package object generate { // Streams from ArrayList (Java) - implicit val getsParStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { - new MakesParallelStream[java.lang.Integer, IntStream] { + implicit val getsParStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesParallelStream[Int, IntStream]) = ali => { + new MakesParallelStream[Int, IntStream] { def parStream: IntStream = ali. asInstanceOf[java.util.ArrayList[java.lang.Integer]]. parallelStream.parallel. mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) } } - implicit val getsSeqStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { - new MakesSequentialStream[java.lang.Integer, IntStream] { + implicit val getsSeqStreamFromArrayListInt: (java.util.ArrayList[Int] => MakesSequentialStream[Int, IntStream]) = ali => { + new MakesSequentialStream[Int, IntStream] { def seqStream: IntStream = ali. asInstanceOf[java.util.ArrayList[java.lang.Integer]]. stream(). @@ -187,16 +188,16 @@ package object generate { // Streams from LinkedList (Java) - implicit val getsParStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesParallelStream[java.lang.Integer, IntStream]) = ali => { - new MakesParallelStream[java.lang.Integer, IntStream] { + implicit val getsParStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesParallelStream[Int, IntStream]) = ali => { + new MakesParallelStream[Int, IntStream] { def parStream: IntStream = ali. asInstanceOf[java.util.LinkedList[java.lang.Integer]]. parallelStream.parallel. mapToInt(new java.util.function.ToIntFunction[java.lang.Integer]{ def applyAsInt(i: java.lang.Integer) = i.intValue }) } } - implicit val getsSeqStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesSequentialStream[java.lang.Integer, IntStream]) = ali => { - new MakesSequentialStream[java.lang.Integer, IntStream] { + implicit val getsSeqStreamFromLinkedListInt: (java.util.LinkedList[Int] => MakesSequentialStream[Int, IntStream]) = ali => { + new MakesSequentialStream[Int, IntStream] { def seqStream: IntStream = ali. asInstanceOf[java.util.LinkedList[java.lang.Integer]]. stream(). diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java index 21af821..5afbde7 100644 --- a/src/main/java/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -482,9 +482,9 @@ public static DoubleStream doubleStreamAccumulatedValues(scala.collection.Map MakesStepper[AnyStepper[A] with EfficientSubstep]) - extends MakesParallelStream[A, Stream[A]] { - def parStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichAnyKeySteppableWithParKeyStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K] with EfficientSubstep]) { - def parKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichAnyValueSteppableWithParValueStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V] with EfficientSubstep]) { - def parValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper.anticipateParallelism, true) - } - implicit class EnrichScalaCollectionWithSeqStream[A, CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[A]]) - extends MakesSequentialStream[A, Stream[A]] { - def seqStream: Stream[A] = StreamSupport.stream(steppize(cc).stepper, false) - } - implicit class EnrichScalaCollectionWithKeySeqStream[K, CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[K]]) { - def seqKeyStream: Stream[K] = StreamSupport.stream(steppize(cc).keyStepper, false) - } - implicit class EnrichScalaCollectionWithValueSeqStream[V, CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[V]]) { - def seqValueStream: Stream[V] = StreamSupport.stream(steppize(cc).valueStepper, false) - } +sealed trait StreamShape[T, S <: BaseStream[_, S]] { + def fromStepper (mk: MakesStepper[T, _], par: Boolean): S + def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S + def fromValueStepper(mk: MakesKeyValueStepper[_, T, _], par: Boolean): S } +object StreamShape extends StreamShapeLowPrio { + // primitive + implicit val IntValue = intStreamShape[Int] + implicit val LongValue = longStreamShape[Long] + implicit val DoubleValue = doubleStreamShape[Double] -trait Priority3StreamConverters extends Priority4StreamConverters { - // Prefer to unbox and widen small primitive types over keeping them boxed - implicit class EnrichBoxedFloatSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Float] with EfficientSubstep]) - extends MakesParallelStream[java.lang.Double, DoubleStream] { - def parStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).stepper.anticipateParallelism), true) - } - implicit class EnrichBoxedFloatKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Float] with EfficientSubstep]) { - def parKeyStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).keyStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedFloatValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Float] with EfficientSubstep]) { - def parValueStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).valueStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedByteSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Byte] with EfficientSubstep]) - extends MakesParallelStream[java.lang.Integer, IntStream] { - def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).stepper.anticipateParallelism), true) - } - implicit class EnrichBoxedByteKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Byte] with EfficientSubstep]) { - def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).keyStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedByteValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Byte] with EfficientSubstep]) { - def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).valueStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedShortSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Short] with EfficientSubstep]) - extends MakesParallelStream[java.lang.Integer, IntStream] { - def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).stepper.anticipateParallelism), true) - } - implicit class EnrichBoxedShortKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Short] with EfficientSubstep]) { - def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).keyStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedShortValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Short] with EfficientSubstep]) { - def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).valueStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedCharSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Char] with EfficientSubstep]) - extends MakesParallelStream[java.lang.Integer, IntStream] { - def parStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).stepper.anticipateParallelism), true) - } - implicit class EnrichBoxedCharKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Char] with EfficientSubstep]) { - def parKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).keyStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedCharValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Char] with EfficientSubstep]) { - def parValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).valueStepper.anticipateParallelism), true) - } - implicit class EnrichBoxedFloatSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Float]]) - extends MakesSequentialStream[java.lang.Double, DoubleStream] { - def seqStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).stepper), false) - } - implicit class EnrichBoxedFloatKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Float]]) { - def seqKeyStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).keyStepper), false) - } - implicit class EnrichBoxedFloatValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Float]]) { - def seqValueStream: DoubleStream = StreamSupport.doubleStream(new Stepper.WideningFloatStepper(steppize(cc).valueStepper), false) - } - implicit class EnrichBoxedByteSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Byte]]) - extends MakesSequentialStream[java.lang.Integer, IntStream] { - def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).stepper), false) - } - implicit class EnrichBoxedByteKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Byte]]) { - def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).keyStepper), false) - } - implicit class EnrichBoxedByteValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Byte]]) { - def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningByteStepper(steppize(cc).valueStepper), false) - } - implicit class EnrichBoxedShortSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Short]]) - extends MakesSequentialStream[java.lang.Integer, IntStream] { - def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).stepper), false) - } - implicit class EnrichBoxedShortKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Short]]) { - def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).keyStepper), false) + // widening + implicit val ByteValue = intStreamShape[Byte] + implicit val ShortValue = intStreamShape[Short] + implicit val CharValue = intStreamShape[Char] + implicit val FloatValue = doubleStreamShape[Float] +} +trait StreamShapeLowPrio { + protected[this] abstract class BaseStreamShape[T, S <: BaseStream[_, S], St <: Stepper[_]](implicit ss: StepperShape[T, St]) extends StreamShape[T, S] { + final def fromStepper (mk: MakesStepper[T, _], par: Boolean): S = stream(mk.stepper, par) + final def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S = stream(mk.keyStepper, par) + final def fromValueStepper(mk: MakesKeyValueStepper[_, T, _], par: Boolean): S = stream(mk.valueStepper, par) + @inline private[this] def stream(st: St, par: Boolean): S = mkStream(if(par) st.anticipateParallelism else st, par) + protected[this] def mkStream(st: St, par: Boolean): S } - implicit class EnrichBoxedShortValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Short]]) { - def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningShortStepper(steppize(cc).valueStepper), false) + protected[this] def intStreamShape[T](implicit ss: StepperShape[T, IntStepper]): StreamShape[T, IntStream] = new BaseStreamShape[T, IntStream, IntStepper] { + protected[this] def mkStream(st: IntStepper, par: Boolean): IntStream = StreamSupport.intStream(st, par) } - implicit class EnrichBoxedCharSteppableWithSeqStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[AnyStepper[Char]]) - extends MakesSequentialStream[java.lang.Integer, IntStream] { - def seqStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).stepper), false) + protected[this] def longStreamShape[T](implicit ss: StepperShape[T, LongStepper]): StreamShape[T, LongStream] = new BaseStreamShape[T, LongStream, LongStepper] { + protected[this] def mkStream(st: LongStepper, par: Boolean): LongStream = StreamSupport.longStream(st, par) } - implicit class EnrichBoxedCharKeySteppableWithSeqKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[AnyStepper[Char]]) { - def seqKeyStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).keyStepper), false) + protected[this] def doubleStreamShape[T](implicit ss: StepperShape[T, DoubleStepper]): StreamShape[T, DoubleStream] = new BaseStreamShape[T, DoubleStream, DoubleStepper] { + protected[this] def mkStream(st: DoubleStepper, par: Boolean): DoubleStream = StreamSupport.doubleStream(st, par) } - implicit class EnrichBoxedCharValueSteppableWithSeqValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[AnyStepper[Char]]) { - def seqValueStream: IntStream = StreamSupport.intStream(new Stepper.WideningCharStepper(steppize(cc).valueStepper), false) + + // reference + implicit def anyStreamShape[T]: StreamShape[T, Stream[T]] = new BaseStreamShape[T, Stream[T], AnyStepper[T]] { + protected[this] def mkStream(st: AnyStepper[T], par: Boolean): Stream[T] = StreamSupport.stream(st, par) } } -trait Priority2StreamConverters extends Priority3StreamConverters { - implicit class EnrichDoubleSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper with EfficientSubstep]) - extends MakesParallelStream[java.lang.Double, DoubleStream] { - def parStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichDoubleKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper with EfficientSubstep]) { - def parKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichDoubleValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper with EfficientSubstep]) { - def parValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper.anticipateParallelism, true) - } - implicit class EnrichIntSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper with EfficientSubstep]) - extends MakesParallelStream[java.lang.Integer, IntStream] { - def parStream: IntStream = StreamSupport.intStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichIntKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper with EfficientSubstep]) { - def parKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichIntValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper with EfficientSubstep]) { - def parValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper.anticipateParallelism, true) - } - implicit class EnrichLongSteppableWithParStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper with EfficientSubstep]) - extends MakesParallelStream[java.lang.Long, LongStream] { - def parStream: LongStream = StreamSupport.longStream(steppize(cc).stepper.anticipateParallelism, true) - } - implicit class EnrichLongKeySteppableWithParKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper with EfficientSubstep]) { - def parKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper.anticipateParallelism, true) - } - implicit class EnrichLongValueSteppableWithParValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper with EfficientSubstep]) { - def parValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper.anticipateParallelism, true) - } - implicit class EnrichScalaCollectionWithSeqDoubleStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[DoubleStepper]) - extends MakesSequentialStream[java.lang.Double, DoubleStream] { - def seqStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).stepper, false) - } - implicit class EnrichScalaCollectionWithSeqIntStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[IntStepper]) - extends MakesSequentialStream[java.lang.Integer, IntStream] { - def seqStream: IntStream = StreamSupport.intStream(steppize(cc).stepper, false) - } - implicit class EnrichScalaCollectionWithSeqLongStream[CC](cc: CC)(implicit steppize: CC => MakesStepper[LongStepper]) - extends MakesSequentialStream[java.lang.Long, LongStream] { - def seqStream: LongStream = StreamSupport.longStream(steppize(cc).stepper, false) - } - implicit class EnrichScalaCollectionWithSeqDoubleKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[DoubleStepper]) { - def seqKeyStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).keyStepper, false) +trait PrimitiveStreamAccumulator[S, AA] { + def streamAccumulate(stream: S): AA +} + +trait PrimitiveStreamUnboxer[A, S] { + def apply(boxed: Stream[A]): S +} + +trait Priority2StreamConverters { + implicit class EnrichAnySteppableWithParStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesStepper[A, EfficientSubstep], ss: StreamShape[A, S]) + extends MakesParallelStream[A, S] { + def parStream: S = ss.fromStepper(steppize(cc), true) } - implicit class EnrichScalaCollectionWithSeqIntKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[IntStepper]) { - def seqKeyStream: IntStream = StreamSupport.intStream(steppize(cc).keyStepper, false) + implicit class EnrichAnySteppableWithSeqStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesStepper[A, Any], ss: StreamShape[A, S]) + extends MakesSequentialStream[A, S] { + def seqStream: S = ss.fromStepper(steppize(cc), false) } - implicit class EnrichScalaCollectionWithSeqLongKeyStream[CC](cc: CC)(implicit steppize: CC => MakesKeyStepper[LongStepper]) { - def seqKeyStream: LongStream = StreamSupport.longStream(steppize(cc).keyStepper, false) + implicit class EnrichAnySteppableWithParKeyStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[A, _, EfficientSubstep], ss: StreamShape[A, S]) { + def parKeyStream: S = ss.fromKeyStepper(steppize(cc), true) } - implicit class EnrichScalaCollectionWithSeqDoubleValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[DoubleStepper]) { - def seqValueStream: DoubleStream = StreamSupport.doubleStream(steppize(cc).valueStepper, false) + implicit class EnrichScalaCollectionWithSeqKeyStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[A, _, Any], ss: StreamShape[A, S]) { + def seqKeyStream: S = ss.fromKeyStepper(steppize(cc), false) } - implicit class EnrichScalaCollectionWithSeqIntValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[IntStepper]) { - def seqValueStream: IntStream = StreamSupport.intStream(steppize(cc).valueStepper, false) + implicit class EnrichAnySteppableWithParValueStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[_, A, EfficientSubstep], ss: StreamShape[A, S]) { + def parValueStream: S = ss.fromValueStepper(steppize(cc), true) } - implicit class EnrichScalaCollectionWithSeqLongValueStream[CC](cc: CC)(implicit steppize: CC => MakesValueStepper[LongStepper]) { - def seqValueStream: LongStream = StreamSupport.longStream(steppize(cc).valueStepper, false) + implicit class EnrichScalaCollectionWithSeqValueStream[A, S <: BaseStream[_, S], CC](cc: CC)(implicit steppize: CC => MakesKeyValueStepper[_, A, Any], ss: StreamShape[A, S]) { + def seqValueStream: S = ss.fromValueStepper(steppize(cc), false) } } @@ -275,37 +178,37 @@ with converterImpl.Priority1StepConverters with converterImpl.Priority1AccumulatorConverters { implicit final class EnrichDoubleArrayWithStream(private val a: Array[Double]) - extends AnyVal with MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { + extends AnyVal with MakesSequentialStream[Double, DoubleStream] with MakesParallelStream[Double, DoubleStream] { def seqStream: DoubleStream = java.util.Arrays.stream(a) def parStream: DoubleStream = seqStream.parallel } implicit final class EnrichIntArrayWithStream(private val a: Array[Int]) - extends AnyVal with MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { + extends AnyVal with MakesSequentialStream[Int, IntStream] with MakesParallelStream[Int, IntStream] { def seqStream: IntStream = java.util.Arrays.stream(a) def parStream: IntStream = seqStream.parallel } implicit final class EnrichLongArrayWithStream(private val a: Array[Long]) - extends AnyVal with MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { + extends AnyVal with MakesSequentialStream[Long, LongStream] with MakesParallelStream[Long, LongStream] { def seqStream: LongStream = java.util.Arrays.stream(a) def parStream: LongStream = seqStream.parallel } implicit final class EnrichDoubleWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Double]) - extends AnyVal with MakesSequentialStream[java.lang.Double, DoubleStream] with MakesParallelStream[java.lang.Double, DoubleStream] { + extends AnyVal with MakesSequentialStream[Double, DoubleStream] with MakesParallelStream[Double, DoubleStream] { def seqStream: DoubleStream = java.util.Arrays.stream(a.array) def parStream: DoubleStream = seqStream.parallel } implicit final class EnrichIntWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Int]) - extends AnyVal with MakesSequentialStream[java.lang.Integer, IntStream] with MakesParallelStream[java.lang.Integer, IntStream] { + extends AnyVal with MakesSequentialStream[Int, IntStream] with MakesParallelStream[Int, IntStream] { def seqStream: IntStream = java.util.Arrays.stream(a.array) def parStream: IntStream = seqStream.parallel } implicit final class EnrichLongWrappedArrayWithStream(private val a: collection.mutable.WrappedArray[Long]) - extends AnyVal with MakesSequentialStream[java.lang.Long, LongStream] with MakesParallelStream[java.lang.Long, LongStream] { + extends AnyVal with MakesSequentialStream[Long, LongStream] with MakesParallelStream[Long, LongStream] { def seqStream: LongStream = java.util.Arrays.stream(a.array) def parStream: LongStream = seqStream.parallel } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index e315024..1ca95dd 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -564,41 +564,64 @@ object Stepper { case _ => new OfLongSpliterator(sp) } - /* These adapter classes can wrap an AnyStepper of a small numeric type into the appropriately widened - * primitive Stepper type. This provides a basis for more efficient stream processing on unboxed values - * provided that the original source of the data is already boxed. In other cases the widening conversion - * should always be performed directly on the original unboxed values in a custom Stepper implementation - * (see for example StepsWidenedByteArray). */ + /* These adapter classes can wrap an AnyStepper of anumeric type into a possibly widened primitive Stepper type. + * This provides a basis for more efficient stream processing on unboxed values provided that the original source + * of the data is boxed. In other cases native implementations of the primitive stepper types should be provided + * (see for example StepsIntArray and StepsWidenedByteArray). */ - private[java8] class WideningByteStepper(st: AnyStepper[Byte]) extends IntStepper { + private[java8] class UnboxingDoubleStepper(st: AnyStepper[Double]) extends DoubleStepper { + def hasNext(): Boolean = st.hasNext() + def nextDouble(): Double = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): DoubleStepper = new UnboxingDoubleStepper(st.substep()) + } + + private[java8] class UnboxingIntStepper(st: AnyStepper[Int]) extends IntStepper { + def hasNext(): Boolean = st.hasNext() + def nextInt(): Int = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): IntStepper = new UnboxingIntStepper(st.substep()) + } + + private[java8] class UnboxingLongStepper(st: AnyStepper[Long]) extends LongStepper { + def hasNext(): Boolean = st.hasNext() + def nextLong(): Long = st.next() + def characteristics(): Int = st.characteristics() + def estimateSize(): Long = st.estimateSize() + def substep(): LongStepper = new UnboxingLongStepper(st.substep()) + } + + private[java8] class UnboxingByteStepper(st: AnyStepper[Byte]) extends IntStepper { def hasNext(): Boolean = st.hasNext() def nextInt(): Int = st.next() def characteristics(): Int = st.characteristics() | NonNull def estimateSize(): Long = st.estimateSize() - def substep(): IntStepper = new WideningByteStepper(st.substep()) + def substep(): IntStepper = new UnboxingByteStepper(st.substep()) } - private[java8] class WideningCharStepper(st: AnyStepper[Char]) extends IntStepper { + private[java8] class UnboxingCharStepper(st: AnyStepper[Char]) extends IntStepper { def hasNext(): Boolean = st.hasNext() def nextInt(): Int = st.next() def characteristics(): Int = st.characteristics() | NonNull def estimateSize(): Long = st.estimateSize() - def substep(): IntStepper = new WideningCharStepper(st.substep()) + def substep(): IntStepper = new UnboxingCharStepper(st.substep()) } - private[java8] class WideningShortStepper(st: AnyStepper[Short]) extends IntStepper { + private[java8] class UnboxingShortStepper(st: AnyStepper[Short]) extends IntStepper { def hasNext(): Boolean = st.hasNext() def nextInt(): Int = st.next() def characteristics(): Int = st.characteristics() | NonNull def estimateSize(): Long = st.estimateSize() - def substep(): IntStepper = new WideningShortStepper(st.substep()) + def substep(): IntStepper = new UnboxingShortStepper(st.substep()) } - private[java8] class WideningFloatStepper(st: AnyStepper[Float]) extends DoubleStepper { + private[java8] class UnboxingFloatStepper(st: AnyStepper[Float]) extends DoubleStepper { def hasNext(): Boolean = st.hasNext() def nextDouble(): Double = st.next() def characteristics(): Int = st.characteristics() | NonNull def estimateSize(): Long = st.estimateSize() - def substep(): DoubleStepper = new WideningFloatStepper(st.substep()) + def substep(): DoubleStepper = new UnboxingFloatStepper(st.substep()) } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index 55c31f5..1079d24 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -5,27 +5,117 @@ import language.implicitConversions import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ -/** Classes or objects implementing this trait create streams suitable for sequential use */ -trait MakesSequentialStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { - def seqStream: SS +trait MakesStepper[T, +Extra] extends Any { + /** Generates a fresh stepper of type `S` for element type `T` */ + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]): S with Extra } -/** Classes or objects implementing this trait create streams suitable for parallel use */ -trait MakesParallelStream[A, SS <: java.util.stream.BaseStream[A, SS]] extends Any { - def parStream: SS +trait MakesKeyValueStepper[K, V, +Extra] extends Any { + /** Generates a fresh stepper of type `S` over map keys of type `K` */ + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]): S with Extra + + /** Generates a fresh stepper of type `S` over map values of type `V` */ + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]): S with Extra +} + +sealed trait StepperShape[T, S <: Stepper[_]] { def ref: Boolean } +object StepperShape extends StepperShapeLowPrio { + private[this] def valueShape[T, S <: Stepper[_]]: StepperShape[T, S] = new StepperShape[T, S] { def ref = false } + + // primitive + implicit val IntValue = valueShape[Int, IntStepper] + implicit val LongValue = valueShape[Long, LongStepper] + implicit val DoubleValue = valueShape[Double, DoubleStepper] + + // widening + implicit val ByteValue = valueShape[Byte, IntStepper] + implicit val ShortValue = valueShape[Short, IntStepper] + implicit val CharValue = valueShape[Char, IntStepper] + implicit val FloatValue = valueShape[Float, DoubleStepper] +} +trait StepperShapeLowPrio { + // reference + implicit def anyStepperShape[T]: StepperShape[T, AnyStepper[T]] = new StepperShape[T, AnyStepper[T]] { def ref = true } } -trait MakesStepper[+T <: Stepper[_]] extends Any { - /** Generates a fresh stepper of type `T` */ - def stepper: T +/** Superclass for `MakesStepper` implementations which support parallelization. At least the `AnyStepper` case must be + * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ +trait MakesParStepper[T] extends Any with MakesStepper[T, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep + case _ => throw new NotImplementedError("AnyStepper must be handled in `stepper` implementations") + }).asInstanceOf[S with EfficientSubstep] } -trait MakesKeyStepper[+T <: Stepper[_]] extends Any { - /** Generates a fresh stepper of type `T` over map keys */ - def keyStepper: T +/** Superclass for `MakesStepper` implementations which do not support parallelization. At least the `AnyStepper` case must be + * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ +trait MakesSeqStepper[T] extends Any with MakesStepper[T, Any] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Int ]]) + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Long ]]) + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Double]]) + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Byte ]]) + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Short ]]) + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Char ]]) + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Float ]]) + case _ => throw new NotImplementedError("AnyStepper must be handled in `stepper` implementations") + }).asInstanceOf[S] } -trait MakesValueStepper[+T <: Stepper[_]] extends Any { - /** Generates a fresh stepper of type `T` over map values */ - def valueStepper: T +/** Superclass for `MakesKeyalueStepper` implementations which support parallelization. At least the `AnyStepper` case must be + * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ +trait MakesKeyValueParStepper[K, V] extends Any with MakesKeyValueStepper[K, V, EfficientSubstep] { + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep + case _ => throw new NotImplementedError("AnyStepper case must be handled in `keyStepper` implementations") + }).asInstanceOf[S with EfficientSubstep] + + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep + case _ => throw new NotImplementedError("AnyStepper case must be handled in `valueStepper` implementations") + }).asInstanceOf[S with EfficientSubstep] +} + +/** Superclass for `MakesKeyalueStepper` implementations which do not support parallelization. At least the `AnyStepper` case must be + * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ +trait MakesKeyValueSeqStepper[K, V] extends Any with MakesKeyValueStepper[K, V, Any] { + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Int ]]) + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Long ]]) + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Double]]) + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Byte ]]) + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Short ]]) + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Char ]]) + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Float ]]) + case _ => throw new NotImplementedError("AnyStepper case must be handled in `keyStepper` implementations") + }).asInstanceOf[S] + + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { + case StepperShape.IntValue => new Stepper.UnboxingIntStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Int ]]) + case StepperShape.LongValue => new Stepper.UnboxingLongStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Long ]]) + case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Double]]) + case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Byte ]]) + case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Short ]]) + case StepperShape.CharValue => new Stepper.UnboxingCharStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Char ]]) + case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Float ]]) + case _ => throw new NotImplementedError("AnyStepper case must be handled in `valueStepper` implementations") + }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala index f27900f..566c17c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala @@ -7,136 +7,28 @@ import scala.compat.java8.runtime._ import Stepper._ -trait Priority7StepConverters { +trait Priority3StepConverters { implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) -} - -trait Priority6StepConverters extends Priority7StepConverters { - implicit def richDoubleIterableCanStep(underlying: Iterable[Double]) = new RichDoubleIterableCanStep(underlying) - implicit def richIntIterableCanStep(underlying: Iterable[Int]) = new RichIntIterableCanStep(underlying) - implicit def richLongIterableCanStep(underlying: Iterable[Long]) = new RichLongIterableCanStep(underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) } -trait Priority5StepConverters extends Priority6StepConverters { - implicit def richDoubleKeyMapCanStep[V](underlying: collection.Map[Double, V]) = new RichDoubleKeyMapCanStep(underlying) - implicit def richDoubleValueMapCanStep[K](underlying: collection.Map[K, Double]) = new RichDoubleValueMapCanStep(underlying) - implicit def richIntKeyMapCanStep[V](underlying: collection.Map[Int, V]) = new RichIntKeyMapCanStep(underlying) - implicit def richIntValueMapCanStep[K](underlying: collection.Map[K, Int]) = new RichIntValueMapCanStep(underlying) - implicit def richLongKeyMapCanStep[V](underlying: collection.Map[Long, V]) = new RichLongKeyMapCanStep(underlying) - implicit def richLongValueMapCanStep[K](underlying: collection.Map[K, Long]) = new RichLongValueMapCanStep(underlying) -} - -trait Priority4StepConverters extends Priority5StepConverters { - implicit def richLinearSeqCanStep[A, CC[A] >: Null <: collection.LinearSeqLike[A, CC[A]]](underlying: CC[A]) = new RichLinearSeqCanStep[A, CC[A]](underlying) - implicit def richHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](underlying: collection.mutable.HashTable[K, HE]) = - new RichHashTableKeyCanStep[K, HE](underlying) - implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableCanStep[K, V](underlying) - implicit def richDefaultHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = - new RichDefaultHashTableValueCanStep[K, V](underlying) - implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableCanStep[K, V](underlying) - implicit def richLinkedHashTableValueCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = - new RichLinkedHashTableValueCanStep[K, V](underlying) +trait Priority2StepConverters extends Priority3StepConverters { + implicit def richLinearSeqCanStep[A](underlying: collection.LinearSeq[A]) = new RichLinearSeqCanStep[A](underlying) + implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = new RichIndexedSeqCanStep[A](underlying) } -trait Priority3StepConverters extends Priority4StepConverters { - implicit def richArrayAnyCanStep[A](underlying: Array[A]) = new RichArrayAnyCanStep[A](underlying) - implicit def richIndexedSeqCanStep[A](underlying: collection.IndexedSeqLike[A, _]) = - new RichIndexedSeqCanStep[A](underlying) +trait Priority1StepConverters extends Priority2StepConverters { + implicit def richDefaultHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) = new RichDefaultHashTableCanStep[K, V](underlying) + implicit def richLinkedHashTableCanStep[K, V](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) = new RichLinkedHashTableCanStep[K, V](underlying) + implicit def richArrayCanStep[A](underlying: Array[A]) = new RichArrayCanStep[A](underlying) + implicit def richWrappedArrayCanStep[A](underlying: collection.mutable.WrappedArray[A]) = new RichArrayCanStep[A](underlying.array) implicit def richFlatHashTableCanStep[A](underlying: collection.mutable.FlatHashTable[A]) = new RichFlatHashTableCanStep[A](underlying) - implicit def richDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](underlying: CC) = - new RichDoubleLinearSeqCanStep[CC](underlying) - implicit def richIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](underlying: CC) = - new RichIntLinearSeqCanStep[CC](underlying) - implicit def richLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](underlying: CC) = - new RichLongLinearSeqCanStep[CC](underlying) implicit def richIteratorCanStep[A](underlying: Iterator[A]) = new RichIteratorCanStep(underlying) - implicit def richHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](underlying: collection.mutable.HashTable[Double, HE]) = - new RichHashTableDoubleKeyCanStep[HE](underlying) - implicit def richHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](underlying: collection.mutable.HashTable[Int, HE]) = - new RichHashTableIntKeyCanStep[HE](underlying) - implicit def richHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](underlying: collection.mutable.HashTable[Long, HE]) = - new RichHashTableLongKeyCanStep[HE](underlying) - implicit def richDefaultHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) = - new RichDefaultHashTableDoubleValueCanStep[K](underlying) - implicit def richDefaultHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) = - new RichDefaultHashTableIntValueCanStep[K](underlying) - implicit def richDefaultHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) = - new RichDefaultHashTableLongValueCanStep[K](underlying) - implicit def richLinkedHashTableDoubleValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) = - new RichLinkedHashTableDoubleValueCanStep[K](underlying) - implicit def richLinkedHashTableIntValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) = - new RichLinkedHashTableIntValueCanStep[K](underlying) - implicit def richLinkedHashTableLongValueCanStep[K](underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) = - new RichLinkedHashTableLongValueCanStep[K](underlying) - implicit def richImmHashMapCanStep[K, V](underlying: collection.immutable.HashMap[K, V]) = new RichImmHashMapCanStep[K, V](underlying) implicit def richImmHashSetCanStep[A](underlying: collection.immutable.HashSet[A]) = new RichImmHashSetCanStep[A](underlying) -} - -trait Priority2StepConverters extends Priority3StepConverters { - implicit def richArrayObjectCanStep[A <: Object](underlying: Array[A]) = new RichArrayObjectCanStep[A](underlying) - implicit def richArrayUnitCanStep(underlying: Array[Unit]) = new RichArrayUnitCanStep(underlying) - implicit def richArrayBooleanCanStep(underlying: Array[Boolean]) = new RichArrayBooleanCanStep(underlying) - implicit def richArrayByteCanStep(underlying: Array[Byte]) = new RichArrayByteCanStep(underlying) - implicit def richArrayCharCanStep(underlying: Array[Char]) = new RichArrayCharCanStep(underlying) - implicit def richArrayShortCanStep(underlying: Array[Short]) = new RichArrayShortCanStep(underlying) - implicit def richArrayFloatCanStep(underlying: Array[Float]) = new RichArrayFloatCanStep(underlying) - - // No special cases for AnyStepper-producing WrappedArrays; they are treated as IndexedSeqs - implicit def richWrappedArrayByteCanStep(underlying: collection.mutable.WrappedArray[Byte]) = new RichArrayByteCanStep(underlying.array) - implicit def richWrappedArrayCharCanStep(underlying: collection.mutable.WrappedArray[Char]) = new RichArrayCharCanStep(underlying.array) - implicit def richWrappedArrayShortCanStep(underlying: collection.mutable.WrappedArray[Short]) = new RichArrayShortCanStep(underlying.array) - implicit def richWrappedArrayFloatCanStep(underlying: collection.mutable.WrappedArray[Float]) = new RichArrayFloatCanStep(underlying.array) - - implicit def richDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](underlying: CC) = - new RichDoubleIndexedSeqCanStep[CC](underlying) - implicit def richIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](underlying: CC) = - new RichIntIndexedSeqCanStep[CC](underlying) - implicit def richLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](underlying: CC) = - new RichLongIndexedSeqCanStep[CC](underlying) implicit def richNumericRangeCanStep[T](underlying: collection.immutable.NumericRange[T]) = new RichNumericRangeCanStep(underlying) implicit def richVectorCanStep[A](underlying: Vector[A]) = new RichVectorCanStep[A](underlying) - implicit def richDoubleFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Double]) = new RichDoubleFlatHashTableCanStep(underlying) - implicit def richIntFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Int]) = new RichIntFlatHashTableCanStep(underlying) - implicit def richLongFlatHashTableCanStep(underlying: collection.mutable.FlatHashTable[Long]) = new RichLongFlatHashTableCanStep(underlying) - implicit def richDoubleIteratorCanStep(underlying: Iterator[Double]) = new RichDoubleIteratorCanStep(underlying) - implicit def richIntIteratorCanStep(underlying: Iterator[Int]) = new RichIntIteratorCanStep(underlying) - implicit def richLongIteratorCanStep(underlying: Iterator[Long]) = new RichLongIteratorCanStep(underlying) - - implicit def richImmHashMapDoubleKeyCanStep[V](underlying: collection.immutable.HashMap[Double, V]) = new RichImmHashMapDoubleKeyCanStep(underlying) - implicit def richImmHashMapDoubleValueCanStep[K](underlying: collection.immutable.HashMap[K, Double]) = new RichImmHashMapDoubleValueCanStep(underlying) - implicit def richImmHashMapIntKeyCanStep[V](underlying: collection.immutable.HashMap[Int, V]) = new RichImmHashMapIntKeyCanStep(underlying) - implicit def richImmHashMapIntValueCanStep[K](underlying: collection.immutable.HashMap[K, Int]) = new RichImmHashMapIntValueCanStep(underlying) - implicit def richImmHashMapLongKeyCanStep[V](underlying: collection.immutable.HashMap[Long, V]) = new RichImmHashMapLongKeyCanStep(underlying) - implicit def richImmHashMapLongValueCanStep[K](underlying: collection.immutable.HashMap[K, Long]) = new RichImmHashMapLongValueCanStep(underlying) - implicit def richBitSetCanStep(underlying: collection.BitSet) = new RichBitSetCanStep(underlying) -} - -trait Priority1StepConverters extends Priority2StepConverters { - implicit def richArrayDoubleCanStep(underlying: Array[Double]) = new RichArrayDoubleCanStep(underlying) - implicit def richArrayIntCanStep(underlying: Array[Int]) = new RichArrayIntCanStep(underlying) - implicit def richArrayLongCanStep(underlying: Array[Long]) = new RichArrayLongCanStep(underlying) - - implicit def richWrappedArrayDoubleCanStep(underlying: collection.mutable.WrappedArray[Double]) = new RichArrayDoubleCanStep(underlying.array) - implicit def richWrappedArrayIntCanStep(underlying: collection.mutable.WrappedArray[Int]) = new RichArrayIntCanStep(underlying.array) - implicit def richWrappedArrayLongCanStep(underlying: collection.mutable.WrappedArray[Long]) = new RichArrayLongCanStep(underlying.array) - - implicit def richIntNumericRangeCanStep(underlying: collection.immutable.NumericRange[Int]) = new RichIntNumericRangeCanStep(underlying) - implicit def richLongNumericRangeCanStep(underlying: collection.immutable.NumericRange[Long]) = new RichLongNumericRangeCanStep(underlying) implicit def richRangeCanStep(underlying: Range) = new RichRangeCanStep(underlying) - - implicit def richDoubleVectorCanStep[A](underlying: Vector[Double]) = new RichDoubleVectorCanStep(underlying) - implicit def richIntVectorCanStep[A](underlying: Vector[Int]) = new RichIntVectorCanStep(underlying) - implicit def richLongVectorCanStep[A](underlying: Vector[Long]) = new RichLongVectorCanStep(underlying) - - implicit def richDoubleHashSetCanStep(underlying: collection.immutable.HashSet[Double]) = new RichDoubleHashSetCanStep(underlying) - implicit def richIntHashSetCanStep(underlying: collection.immutable.HashSet[Int]) = new RichIntHashSetCanStep(underlying) - implicit def richLongHashSetCanStep(underlying: collection.immutable.HashSet[Long]) = new RichLongHashSetCanStep(underlying) - implicit def richStringCanStep(underlying: String) = new RichStringCanStep(underlying) } - diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index 8a960d0..0da150e 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -17,18 +17,6 @@ extends StepsLikeIndexed[A, StepsObjectArray[A]](_i0, _iN) { def semiclone(half: Int) = new StepsObjectArray[A](underlying, i0, half) } -private[java8] class StepsAnyArray[A](underlying: Array[A], _i0: Int, _iN: Int) -extends StepsLikeIndexed[A, StepsAnyArray[A]](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE - def semiclone(half: Int) = new StepsAnyArray[A](underlying, i0, half) -} - -private[java8] class StepsUnitArray(underlying: Array[Unit], _i0: Int, _iN: Int) -extends StepsLikeIndexed[Unit, StepsUnitArray](_i0, _iN) { - def next() = if (hasNext()) { val j = i0; i0 += 1; () } else throwNSEE - def semiclone(half: Int) = new StepsUnitArray(underlying, i0, half) -} - private[java8] class StepsBoxedBooleanArray(underlying: Array[Boolean], _i0: Int, _iN: Int) extends StepsLikeIndexed[Boolean, StepsBoxedBooleanArray](_i0, _iN) { def next() = if (hasNext()) { val j = i0; i0 += 1; underlying(j) } else throwNSEE @@ -81,46 +69,19 @@ extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichArrayAnyCanStep[A](private val underlying: Array[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyArray[A](underlying, 0, underlying.length) -} - -final class RichArrayObjectCanStep[A <: Object](private val underlying: Array[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsObjectArray[A](underlying, 0, underlying.length) -} - -final class RichArrayUnitCanStep(private val underlying: Array[Unit]) extends AnyVal with MakesStepper[AnyStepper[Unit] with EfficientSubstep] { - @inline def stepper: AnyStepper[Unit] with EfficientSubstep = new StepsUnitArray(underlying, 0, underlying.length) -} - -final class RichArrayBooleanCanStep(private val underlying: Array[Boolean]) extends AnyVal with MakesStepper[AnyStepper[Boolean] with EfficientSubstep] { - @inline def stepper: AnyStepper[Boolean] with EfficientSubstep = new StepsBoxedBooleanArray(underlying, 0, underlying.length) -} - -final class RichArrayByteCanStep(private val underlying: Array[Byte]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedByteArray(underlying, 0, underlying.length) -} - -final class RichArrayCharCanStep(private val underlying: Array[Char]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedCharArray(underlying, 0, underlying.length) -} - -final class RichArrayShortCanStep(private val underlying: Array[Short]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsWidenedShortArray(underlying, 0, underlying.length) -} - -final class RichArrayFloatCanStep(private val underlying: Array[Float]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsWidenedFloatArray(underlying, 0, underlying.length) -} - -final class RichArrayDoubleCanStep(private val underlying: Array[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleArray(underlying, 0, underlying.length) -} - -final class RichArrayIntCanStep(private val underlying: Array[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntArray(underlying, 0, underlying.length) -} - -final class RichArrayLongCanStep(private val underlying: Array[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongArray(underlying, 0, underlying.length) +final class RichArrayCanStep[T](private val underlying: Array[T]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => + if(underlying.isInstanceOf[Array[Boolean]]) + new StepsBoxedBooleanArray (underlying.asInstanceOf[Array[Boolean]], 0, underlying.length) + else new StepsObjectArray[AnyRef](underlying.asInstanceOf[Array[AnyRef ]], 0, underlying.length) + case StepperShape.IntValue => new StepsIntArray (underlying.asInstanceOf[Array[Int ]], 0, underlying.length) + case StepperShape.LongValue => new StepsLongArray (underlying.asInstanceOf[Array[Long ]], 0, underlying.length) + case StepperShape.DoubleValue => new StepsDoubleArray (underlying.asInstanceOf[Array[Double ]], 0, underlying.length) + case StepperShape.ByteValue => new StepsWidenedByteArray (underlying.asInstanceOf[Array[Byte ]], 0, underlying.length) + case StepperShape.ShortValue => new StepsWidenedShortArray (underlying.asInstanceOf[Array[Short ]], 0, underlying.length) + case StepperShape.CharValue => new StepsWidenedCharArray (underlying.asInstanceOf[Array[Char ]], 0, underlying.length) + case StepperShape.FloatValue => new StepsWidenedFloatArray (underlying.asInstanceOf[Array[Float ]], 0, underlying.length) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala index 4c9436c..55bae9f 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -53,16 +53,17 @@ extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { // Value class adapter // ///////////////////////// -final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - def stepper: IntStepper with EfficientSubstep = { +final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesParStepper[Int] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = { val bits: Array[Long] = underlying match { case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) case n: collection.immutable.BitSet.BitSetN => RichBitSetCanStep.reflectInternalsN(n) case x => x.toBitMask } - new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt) + new StepsIntBitSet(bits, 0, math.min(bits.length*64L, Int.MaxValue).toInt).asInstanceOf[S with EfficientSubstep] } } + private[java8] object RichBitSetCanStep { private val reflector = classOf[collection.immutable.BitSet.BitSetN].getMethod("elems") def reflectInternalsN(bsn: collection.immutable.BitSet.BitSetN): Array[Long] = reflector.invoke(bsn).asInstanceOf[Array[Long]] diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index fb28870..70dbc76 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -39,30 +39,15 @@ extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { // Value class adapters // ////////////////////////// -final class RichFlatHashTableCanStep[A](private val underlying: collection.mutable.FlatHashTable[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = { +final class RichFlatHashTableCanStep[T](private val underlying: collection.mutable.FlatHashTable[T]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = { val tbl = CollectionInternals.getTable(underlying) - new StepsAnyFlatHashTable(tbl, 0, tbl.length) - } -} - -final class RichDoubleFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable(underlying) - new StepsDoubleFlatHashTable(tbl, 0, tbl.length) - } -} - -final class RichIntFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable(underlying) - new StepsIntFlatHashTable(tbl, 0, tbl.length) - } -} - -final class RichLongFlatHashTableCanStep(private val underlying: collection.mutable.FlatHashTable[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable(underlying) - new StepsLongFlatHashTable(tbl, 0, tbl.length) + (ss match { + case ss if ss.ref => new StepsAnyFlatHashTable[T](tbl, 0, tbl.length) + case StepperShape.IntValue => new StepsIntFlatHashTable (tbl, 0, tbl.length) + case StepperShape.LongValue => new StepsLongFlatHashTable (tbl, 0, tbl.length) + case StepperShape.DoubleValue => new StepsDoubleFlatHashTable(tbl, 0, tbl.length) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala index db68bb7..4a328d1 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -13,28 +13,28 @@ import Stepper._ // Steppers for keys (type of HashEntry doesn't matter) -private[java8] class StepsAnyHashTableKey[K, HE <: collection.mutable.HashEntry[K, HE]](_underlying: Array[collection.mutable.HashEntry[K, HE]], _i0: Int, _iN: Int) -extends StepsLikeGapped[K, StepsAnyHashTableKey[K, HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsAnyHashTableKey[K, HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, HE]]], i0, half) +private[java8] class StepsAnyHashTableKey[K](_underlying: Array[collection.mutable.HashEntry[K, _]], _i0: Int, _iN: Int) +extends StepsLikeGapped[K, StepsAnyHashTableKey[K]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def next() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[K, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[K, _]].next.asInstanceOf[AnyRef]; ans } + def semiclone(half: Int) = new StepsAnyHashTableKey[K](underlying.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], i0, half) } -private[java8] class StepsDoubleHashTableKey[HE <: collection.mutable.HashEntry[Double, HE]](_underlying: Array[collection.mutable.HashEntry[Double, HE]], _i0: Int, _iN: Int) -extends StepsDoubleLikeGapped[StepsDoubleHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsDoubleHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, HE]]], i0, half) +private[java8] class StepsDoubleHashTableKey(_underlying: Array[collection.mutable.HashEntry[Double, _]], _i0: Int, _iN: Int) +extends StepsDoubleLikeGapped[StepsDoubleHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextDouble() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Double, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Double, _]].next.asInstanceOf[AnyRef]; ans } + def semiclone(half: Int) = new StepsDoubleHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], i0, half) } -private[java8] class StepsIntHashTableKey[HE <: collection.mutable.HashEntry[Int, HE]](_underlying: Array[collection.mutable.HashEntry[Int, HE]], _i0: Int, _iN: Int) -extends StepsIntLikeGapped[StepsIntHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsIntHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, HE]]], i0, half) +private[java8] class StepsIntHashTableKey(_underlying: Array[collection.mutable.HashEntry[Int, _]], _i0: Int, _iN: Int) +extends StepsIntLikeGapped[StepsIntHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextInt() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Int, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Int, _]].next.asInstanceOf[AnyRef]; ans } + def semiclone(half: Int) = new StepsIntHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], i0, half) } -private[java8] class StepsLongHashTableKey[HE <: collection.mutable.HashEntry[Long, HE]](_underlying: Array[collection.mutable.HashEntry[Long, HE]], _i0: Int, _iN: Int) -extends StepsLongLikeGapped[StepsLongHashTableKey[HE]](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { - def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[HE].key; currentEntry = currentEntry.asInstanceOf[HE].next; ans } - def semiclone(half: Int) = new StepsLongHashTableKey[HE](underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, HE]]], i0, half) +private[java8] class StepsLongHashTableKey(_underlying: Array[collection.mutable.HashEntry[Long, _]], _i0: Int, _iN: Int) +extends StepsLongLikeGapped[StepsLongHashTableKey](_underlying.asInstanceOf[Array[AnyRef]], _i0, _iN) { + def nextLong() = if (currentEntry eq null) throwNSEE else { val ans = currentEntry.asInstanceOf[collection.mutable.HashEntry[Long, _]].key; currentEntry = currentEntry.asInstanceOf[collection.mutable.HashEntry[Long, _]].next.asInstanceOf[AnyRef]; ans } + def semiclone(half: Int) = new StepsLongHashTableKey(underlying.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], i0, half) } // Steppers for entries stored in DefaultEntry HashEntry @@ -138,122 +138,64 @@ extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInst // Value class adapters // ////////////////////////// -// Steppers for keys (type of HashEntry doesn't matter) - -final class RichHashTableKeyCanStep[K, HE >: Null <: collection.mutable.HashEntry[K, HE]](private val underlying: collection.mutable.HashTable[K, HE]) -extends AnyVal with MakesKeyStepper[AnyStepper[K] with EfficientSubstep] { - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, HE](underlying) - new StepsAnyHashTableKey(tbl, 0, tbl.length) - } -} - -final class RichHashTableDoubleKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Double, HE]](private val underlying: collection.mutable.HashTable[Double, HE]) -extends AnyVal with MakesKeyStepper[DoubleStepper with EfficientSubstep] { - @inline def keyStepper: DoubleStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[Double, HE](underlying) - new StepsDoubleHashTableKey(tbl, 0, tbl.length) - } -} - -final class RichHashTableIntKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Int, HE]](private val underlying: collection.mutable.HashTable[Int, HE]) -extends AnyVal with MakesKeyStepper[IntStepper with EfficientSubstep] { - @inline def keyStepper: IntStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[Int, HE](underlying) - new StepsIntHashTableKey(tbl, 0, tbl.length) - } -} - -final class RichHashTableLongKeyCanStep[HE >: Null <: collection.mutable.HashEntry[Long, HE]](private val underlying: collection.mutable.HashTable[Long, HE]) -extends AnyVal with MakesKeyStepper[LongStepper with EfficientSubstep] { - @inline def keyStepper: LongStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[Long, HE](underlying) - new StepsLongHashTableKey(tbl, 0, tbl.length) - } -} - // Steppers for entries stored in DefaultEntry HashEntry -// (both for key-value pair and for values alone) -final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) -extends AnyVal with MakesStepper[AnyStepper[(K,V)] with EfficientSubstep] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { +final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTable(tbl, 0, tbl.length) + new StepsAnyDefaultHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] } -} -final class RichDefaultHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) -extends AnyVal with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - new StepsAnyDefaultHashTableValue(tbl, 0, tbl.length) + (ss match { + case ss if ss.ref => new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length) + case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) + case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) + case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) + case ss => super.keyStepper(ss) + }).asInstanceOf[S with EfficientSubstep] } -} -final class RichDefaultHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Double]]) -extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Double]](underlying) - new StepsDoubleDefaultHashTableValue(tbl, 0, tbl.length) - } -} - -final class RichDefaultHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Int]]) -extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Int]](underlying) - new StepsIntDefaultHashTableValue(tbl, 0, tbl.length) + override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { + val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) + (ss match { + case ss if ss.ref => new StepsAnyDefaultHashTableValue (tbl, 0, tbl.length) + case StepperShape.IntValue => new StepsIntDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int ]]]], 0, tbl.length) + case StepperShape.LongValue => new StepsLongDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long ]]]], 0, tbl.length) + case StepperShape.DoubleValue => new StepsDoubleDefaultHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], 0, tbl.length) + case ss => super.valueStepper(ss) + }).asInstanceOf[S with EfficientSubstep] } } -final class RichDefaultHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, Long]]) -extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, Long]](underlying) - new StepsLongDefaultHashTableValue(tbl, 0, tbl.length) - } -} - // Steppers for entries stored in LinkedEntry HashEntry -// (both for key-value pair and for values alone) -final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) -extends AnyVal with MakesStepper[AnyStepper[(K,V)] with EfficientSubstep] { - @inline def stepper: AnyStepper[(K,V)] with EfficientSubstep = { +final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTable(tbl, 0, tbl.length) + new StepsAnyLinkedHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] } -} -final class RichLinkedHashTableValueCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) -extends AnyVal with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = { + override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - new StepsAnyLinkedHashTableValue(tbl, 0, tbl.length) + (ss match { + case ss if ss.ref => new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length) + case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) + case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) + case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) + case ss => super.keyStepper(ss) + }).asInstanceOf[S with EfficientSubstep] } -} - -final class RichLinkedHashTableDoubleValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Double]]) -extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { - @inline def valueStepper: DoubleStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Double]](underlying) - new StepsDoubleLinkedHashTableValue(tbl, 0, tbl.length) - } -} -final class RichLinkedHashTableIntValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Int]]) -extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { - @inline def valueStepper: IntStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Int]](underlying) - new StepsIntLinkedHashTableValue(tbl, 0, tbl.length) - } -} - -final class RichLinkedHashTableLongValueCanStep[K](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, Long]]) -extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { - @inline def valueStepper: LongStepper with EfficientSubstep = { - val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, Long]](underlying) - new StepsLongLinkedHashTableValue(tbl, 0, tbl.length) + override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { + val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) + (ss match { + case ss if ss.ref => new StepsAnyLinkedHashTableValue (tbl, 0, tbl.length) + case StepperShape.IntValue => new StepsIntLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int ]]]], 0, tbl.length) + case StepperShape.LongValue => new StepsLongLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long ]]]], 0, tbl.length) + case StepperShape.DoubleValue => new StepsDoubleLinkedHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], 0, tbl.length) + case ss => super.valueStepper(ss) + }).asInstanceOf[S with EfficientSubstep] } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala index d10b9a8..888c1d4 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -125,34 +125,23 @@ extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlyin // Value class adapters // ////////////////////////// -final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) -extends AnyVal with MakesStepper[AnyStepper[(K, V)] with EfficientSubstep] with MakesKeyStepper[AnyStepper[K] with EfficientSubstep] with MakesValueStepper[AnyStepper[V] with EfficientSubstep] { - @inline def stepper: AnyStepper[(K, V)] with EfficientSubstep = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size) - @inline def keyStepper: AnyStepper[K] with EfficientSubstep = new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) - @inline def valueStepper: AnyStepper[V] with EfficientSubstep = new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) +final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = + new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size).asInstanceOf[S with EfficientSubstep] + + override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { + case ss if ss.ref => new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + case StepperShape.IntValue => new StepsIntImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Int, V]], 0, underlying.size) + case StepperShape.LongValue => new StepsLongImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Long, V]], 0, underlying.size) + case StepperShape.DoubleValue => new StepsDoubleImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Double, V]], 0, underlying.size) + case ss => super.keyStepper(ss) + }).asInstanceOf[S with EfficientSubstep] + + override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { + case ss if ss.ref => new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + case StepperShape.IntValue => new StepsIntImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Int]], 0, underlying.size) + case StepperShape.LongValue => new StepsLongImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Long]], 0, underlying.size) + case StepperShape.DoubleValue => new StepsDoubleImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Double]], 0, underlying.size) + case ss => super.valueStepper(ss) + }).asInstanceOf[S with EfficientSubstep] } - -final class RichImmHashMapDoubleKeyCanStep[V](private val underlying: collection.immutable.HashMap[Double, V]) extends AnyVal with MakesKeyStepper[DoubleStepper with EfficientSubstep] { - @inline def keyStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapKey[V](underlying, 0, underlying.size) -} - -final class RichImmHashMapDoubleValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Double]) extends AnyVal with MakesValueStepper[DoubleStepper with EfficientSubstep] { - @inline def valueStepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashMapValue[K](underlying, 0, underlying.size) -} - -final class RichImmHashMapIntKeyCanStep[V](private val underlying: collection.immutable.HashMap[Int, V]) extends AnyVal with MakesKeyStepper[IntStepper with EfficientSubstep] { - @inline def keyStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapKey[V](underlying, 0, underlying.size) -} - -final class RichImmHashMapIntValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Int]) extends AnyVal with MakesValueStepper[IntStepper with EfficientSubstep] { - @inline def valueStepper: IntStepper with EfficientSubstep = new StepsIntImmHashMapValue[K](underlying, 0, underlying.size) -} - -final class RichImmHashMapLongKeyCanStep[V](private val underlying: collection.immutable.HashMap[Long, V]) extends AnyVal with MakesKeyStepper[LongStepper with EfficientSubstep] { - @inline def keyStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapKey[V](underlying, 0, underlying.size) -} - -final class RichImmHashMapLongValueCanStep[K](private val underlying: collection.immutable.HashMap[K, Long]) extends AnyVal with MakesValueStepper[LongStepper with EfficientSubstep] { - @inline def valueStepper: LongStepper with EfficientSubstep = new StepsLongImmHashMapValue[K](underlying, 0, underlying.size) -} - diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala index 75e0c7a..56e0560 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -39,18 +39,12 @@ extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { // Value class adapters // ////////////////////////// -final class RichImmHashSetCanStep[A](private val underlying: collection.immutable.HashSet[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyImmHashSet(underlying.iterator, underlying.size) -} - -final class RichDoubleHashSetCanStep(private val underlying: collection.immutable.HashSet[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleImmHashSet(underlying.iterator, underlying.size) -} - -final class RichIntHashSetCanStep(private val underlying: collection.immutable.HashSet[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntImmHashSet(underlying.iterator, underlying.size) -} - -final class RichLongHashSetCanStep(private val underlying: collection.immutable.HashSet[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongImmHashSet(underlying.iterator, underlying.size) +final class RichImmHashSetCanStep[T](private val underlying: collection.immutable.HashSet[T]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyImmHashSet[T](underlying.iterator, underlying.size) + case StepperShape.IntValue => new StepsIntImmHashSet (underlying.iterator.asInstanceOf[Iterator[Int]], underlying.size) + case StepperShape.LongValue => new StepsLongImmHashSet (underlying.iterator.asInstanceOf[Iterator[Long]], underlying.size) + case StepperShape.DoubleValue => new StepsDoubleImmHashSet(underlying.iterator.asInstanceOf[Iterator[Double]], underlying.size) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index bf00f35..69d3260 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -39,18 +39,12 @@ extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichIndexedSeqCanStep[A](private val underlying: collection.IndexedSeqLike[A, _]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyIndexedSeq[A](underlying, 0, underlying.length) -} - -final class RichDoubleIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Double, _]](private val underlying: CC) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleIndexedSeq[CC](underlying, 0, underlying.length) -} - -final class RichIntIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Int, _]](private val underlying: CC) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntIndexedSeq[CC](underlying, 0, underlying.length) -} - -final class RichLongIndexedSeqCanStep[CC <: collection.IndexedSeqLike[Long, _]](private val underlying: CC) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongIndexedSeq[CC](underlying, 0, underlying.length) +final class RichIndexedSeqCanStep[T](private val underlying: collection.IndexedSeqLike[T, _]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyIndexedSeq[T](underlying, 0, underlying.length) + case StepperShape.IntValue => new StepsIntIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Int, _]], 0, underlying.length) + case StepperShape.LongValue => new StepsLongIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Long, _]], 0, underlying.length) + case StepperShape.DoubleValue => new StepsDoubleIndexedSeq(underlying.asInstanceOf[collection.IndexedSeqLike[Double, _]], 0, underlying.length) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala index 0623119..256d121 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -10,18 +10,12 @@ import Stepper._ // Iterables just defer to iterator unless they can pattern match something better. // TODO: implement pattern matching! -final class RichIterableCanStep[A](private val underlying: Iterable[A]) extends AnyVal with MakesStepper[AnyStepper[A]] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying.iterator) -} - -final class RichDoubleIterableCanStep(private val underlying: Iterable[Double]) extends AnyVal with MakesStepper[DoubleStepper] { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying.iterator) -} - -final class RichIntIterableCanStep(private val underlying: Iterable[Int]) extends AnyVal with MakesStepper[IntStepper] { - @inline def stepper: IntStepper = new StepsIntIterator(underlying.iterator) -} - -final class RichLongIterableCanStep(private val underlying: Iterable[Long]) extends AnyVal with MakesStepper[LongStepper] { - @inline def stepper: LongStepper = new StepsLongIterator(underlying.iterator) +final class RichIterableCanStep[T](private val underlying: Iterable[T]) extends AnyVal with MakesSeqStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyIterator[T](underlying.iterator) + case StepperShape.IntValue => new StepsIntIterator (underlying.iterator.asInstanceOf[Iterator[Int]]) + case StepperShape.LongValue => new StepsLongIterator (underlying.iterator.asInstanceOf[Iterator[Long]]) + case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.iterator.asInstanceOf[Iterator[Double]]) + case ss => super.stepper(ss) + }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala index 89fa367..5058303 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -39,19 +39,12 @@ extends StepsLongLikeIterator[StepsLongIterator](_underlying) { // Value class adapters // ////////////////////////// -final class RichIteratorCanStep[A](private val underlying: Iterator[A]) extends AnyVal with MakesStepper[AnyStepper[A]] { - @inline def stepper: AnyStepper[A] = new StepsAnyIterator[A](underlying) +final class RichIteratorCanStep[T](private val underlying: Iterator[T]) extends AnyVal with MakesSeqStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyIterator[T](underlying) + case StepperShape.IntValue => new StepsIntIterator (underlying.asInstanceOf[Iterator[Int]]) + case StepperShape.LongValue => new StepsLongIterator (underlying.asInstanceOf[Iterator[Long]]) + case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.asInstanceOf[Iterator[Double]]) + case ss => super.stepper(ss) + }).asInstanceOf[S] } - -final class RichDoubleIteratorCanStep(private val underlying: Iterator[Double]) extends AnyVal with MakesStepper[DoubleStepper] { - @inline def stepper: DoubleStepper = new StepsDoubleIterator(underlying) -} - -final class RichIntIteratorCanStep(private val underlying: Iterator[Int]) extends AnyVal with MakesStepper[IntStepper] { - @inline def stepper: IntStepper = new StepsIntIterator(underlying) -} - -final class RichLongIteratorCanStep(private val underlying: Iterator[Long]) extends AnyVal with MakesStepper[LongStepper] { - @inline def stepper: LongStepper = new StepsLongIterator(underlying) -} - diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index 978bc33..c111915 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -11,54 +11,48 @@ import Stepper._ // Stepper implementations // ///////////////////////////// -private[java8] class StepsAnyLinearSeq[A, CC >: Null <: collection.LinearSeqLike[A, CC]](_underlying: CC, _maxN: Long) -extends StepsWithTail[A, CC, StepsAnyLinearSeq[A, CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail +private[java8] class StepsAnyLinearSeq[A](_underlying: collection.LinearSeq[A], _maxN: Long) +extends StepsWithTail[A, collection.LinearSeq[A], StepsAnyLinearSeq[A]](_underlying, _maxN) { + protected def myIsEmpty(cc: collection.LinearSeq[A]): Boolean = cc.isEmpty + protected def myTailOf(cc: collection.LinearSeq[A]) = cc.tail def next() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsAnyLinearSeq[A, CC](underlying, half) + def semiclone(half: Int) = new StepsAnyLinearSeq[A](underlying, half) } -private[java8] class StepsDoubleLinearSeq[CC >: Null <: collection.LinearSeqLike[Double, CC]](_underlying: CC, _maxN: Long) -extends StepsDoubleWithTail[CC, StepsDoubleLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail +private[java8] class StepsDoubleLinearSeq(_underlying: collection.LinearSeq[Double], _maxN: Long) +extends StepsDoubleWithTail[collection.LinearSeq[Double], StepsDoubleLinearSeq](_underlying, _maxN) { + protected def myIsEmpty(cc: collection.LinearSeq[Double]): Boolean = cc.isEmpty + protected def myTailOf(cc: collection.LinearSeq[Double]) = cc.tail def nextDouble() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsDoubleLinearSeq[CC](underlying, half) + def semiclone(half: Int) = new StepsDoubleLinearSeq(underlying, half) } -private[java8] class StepsIntLinearSeq[CC >: Null <: collection.LinearSeqLike[Int, CC]](_underlying: CC, _maxN: Long) -extends StepsIntWithTail[CC, StepsIntLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail +private[java8] class StepsIntLinearSeq(_underlying: collection.LinearSeq[Int], _maxN: Long) +extends StepsIntWithTail[collection.LinearSeq[Int], StepsIntLinearSeq](_underlying, _maxN) { + protected def myIsEmpty(cc: collection.LinearSeq[Int]): Boolean = cc.isEmpty + protected def myTailOf(cc: collection.LinearSeq[Int]) = cc.tail def nextInt() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsIntLinearSeq[CC](underlying, half) + def semiclone(half: Int) = new StepsIntLinearSeq(underlying, half) } -private[java8] class StepsLongLinearSeq[CC >: Null <: collection.LinearSeqLike[Long, CC]](_underlying: CC, _maxN: Long) -extends StepsLongWithTail[CC, StepsLongLinearSeq[CC]](_underlying, _maxN) { - protected def myIsEmpty(cc: CC): Boolean = cc.isEmpty - protected def myTailOf(cc: CC): CC = cc.tail +private[java8] class StepsLongLinearSeq(_underlying: collection.LinearSeq[Long], _maxN: Long) +extends StepsLongWithTail[collection.LinearSeq[Long], StepsLongLinearSeq](_underlying, _maxN) { + protected def myIsEmpty(cc: collection.LinearSeq[Long]): Boolean = cc.isEmpty + protected def myTailOf(cc: collection.LinearSeq[Long]) = cc.tail def nextLong() = if (hasNext()) { maxN -= 1; val ans = underlying.head; underlying = underlying.tail; ans } else throwNSEE - def semiclone(half: Int) = new StepsLongLinearSeq[CC](underlying, half) + def semiclone(half: Int) = new StepsLongLinearSeq(underlying, half) } ////////////////////////// // Value class adapters // ////////////////////////// -final class RichLinearSeqCanStep[A, CC >: Null <: collection.LinearSeqLike[A, CC]](private val underlying: CC) extends AnyVal with MakesStepper[AnyStepper[A]] { - @inline def stepper: AnyStepper[A] = new StepsAnyLinearSeq[A, CC](underlying, Long.MaxValue) -} - -final class RichDoubleLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Double, CC]](private val underlying: CC) extends AnyVal with MakesStepper[DoubleStepper] { - @inline def stepper: DoubleStepper = new StepsDoubleLinearSeq[CC](underlying, Long.MaxValue) -} - -final class RichIntLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Int, CC]](private val underlying: CC) extends AnyVal with MakesStepper[IntStepper] { - @inline def stepper: IntStepper = new StepsIntLinearSeq[CC](underlying, Long.MaxValue) -} - -final class RichLongLinearSeqCanStep[CC >: Null <: collection.LinearSeqLike[Long, CC]](private val underlying: CC) extends AnyVal with MakesStepper[LongStepper] { - @inline def stepper: LongStepper = new StepsLongLinearSeq[CC](underlying, Long.MaxValue) +final class RichLinearSeqCanStep[T](private val underlying: collection.LinearSeq[T]) extends AnyVal with MakesSeqStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyLinearSeq[T](underlying, Long.MaxValue) + case StepperShape.IntValue => new StepsIntLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Int]], Long.MaxValue) + case StepperShape.LongValue => new StepsLongLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Long]], Long.MaxValue) + case StepperShape.DoubleValue => new StepsDoubleLinearSeq(underlying.asInstanceOf[collection.LinearSeq[Double]], Long.MaxValue) + case ss => super.stepper(ss) + }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index 684892c..d5ae3bb 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -10,32 +10,22 @@ import Stepper._ // Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching // TODO: implement pattern matching -final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyStepper[AnyStepper[K]] with MakesValueStepper[AnyStepper[V]] { +final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyValueSeqStepper[K, V] { // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here - def keyStepper: AnyStepper[K] = new StepsAnyIterator[K](underlying.keysIterator) - def valueStepper: AnyStepper[V] = new StepsAnyIterator[V](underlying.valuesIterator) -} - -final class RichDoubleKeyMapCanStep[V](private val underlying: collection.Map[Double, V]) extends AnyVal with MakesKeyStepper[DoubleStepper] { - def keyStepper: DoubleStepper = new StepsDoubleIterator(underlying.keysIterator) -} - -final class RichDoubleValueMapCanStep[K](private val underlying: collection.Map[K, Double]) extends AnyVal with MakesValueStepper[DoubleStepper] { - def valueStepper: DoubleStepper = new StepsDoubleIterator(underlying.valuesIterator) -} - -final class RichIntKeyMapCanStep[V](private val underlying: collection.Map[Int, V]) extends AnyVal with MakesKeyStepper[IntStepper] { - def keyStepper: IntStepper = new StepsIntIterator(underlying.keysIterator) -} - -final class RichIntValueMapCanStep[K](private val underlying: collection.Map[K, Int]) extends AnyVal with MakesValueStepper[IntStepper] { - def valueStepper: IntStepper = new StepsIntIterator(underlying.valuesIterator) -} - -final class RichLongKeyMapCanStep[V](private val underlying: collection.Map[Long, V]) extends AnyVal with MakesKeyStepper[LongStepper] { - def keyStepper: LongStepper = new StepsLongIterator(underlying.keysIterator) -} -final class RichLongValueMapCanStep[K](private val underlying: collection.Map[K, Long]) extends AnyVal with MakesValueStepper[LongStepper] { - def valueStepper: LongStepper = new StepsLongIterator(underlying.valuesIterator) + override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { + case ss if ss.ref => new StepsAnyIterator (underlying.keysIterator) + case StepperShape.IntValue => new StepsIntIterator (underlying.keysIterator.asInstanceOf[Iterator[Int]]) + case StepperShape.LongValue => new StepsLongIterator (underlying.keysIterator.asInstanceOf[Iterator[Long]]) + case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.keysIterator.asInstanceOf[Iterator[Double]]) + case ss => super.keyStepper(ss) + }).asInstanceOf[S] + + override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { + case ss if ss.ref => new StepsAnyIterator (underlying.valuesIterator) + case StepperShape.IntValue => new StepsIntIterator (underlying.valuesIterator.asInstanceOf[Iterator[Int]]) + case StepperShape.LongValue => new StepsLongIterator (underlying.valuesIterator.asInstanceOf[Iterator[Long]]) + case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.valuesIterator.asInstanceOf[Iterator[Double]]) + case ss => super.valueStepper(ss) + }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index e60acee..4dc0eec 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -39,18 +39,16 @@ extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichRangeCanStep(private val underlying: Range) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntRange(underlying, 0, underlying.length) -} - -final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesStepper[AnyStepper[T] with EfficientSubstep] { - @inline def stepper: AnyStepper[T] with EfficientSubstep = new StepsAnyNumericRange[T](underlying, 0, underlying.length) -} - -final class RichIntNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntNumericRange(underlying, 0, underlying.length) +final class RichRangeCanStep[T](private val underlying: Range) extends AnyVal with MakesParStepper[Int] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = + new StepsIntRange(underlying, 0, underlying.length).asInstanceOf[S with EfficientSubstep] } -final class RichLongNumericRangeCanStep(private val underlying: collection.immutable.NumericRange[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongNumericRange(underlying, 0, underlying.length) +final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyNumericRange[T](underlying, 0, underlying.length) + case StepperShape.IntValue => new StepsIntNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Int]], 0, underlying.length) + case StepperShape.LongValue => new StepsLongNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Long]], 0, underlying.length) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index de937b8..85e4706 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -11,7 +11,7 @@ import Stepper._ // Stepper implementation // //////////////////////////// -private[java8] class StepperStringChar(underlying: String, _i0: Int, _iN: Int) +private[java8] class StepperStringChar(underlying: CharSequence, _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepperStringChar](_i0, _iN) { def nextInt() = if (hasNext()) { val j = i0; i0 += 1; underlying.charAt(j) } else throwNSEE def semiclone(half: Int) = new StepperStringChar(underlying, i0, half) @@ -45,8 +45,8 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var // Value class adapter // ///////////////////////// -final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = charStepper +final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesParStepper[Char] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Char, S]) = charStepper.asInstanceOf[S with EfficientSubstep] @inline def charStepper: IntStepper with EfficientSubstep = new StepperStringChar(underlying, 0, underlying.length) @inline def codepointStepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index 132f89b..046a587 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -134,18 +134,12 @@ with StepsVectorLike[Long] { // Value class adapters // ////////////////////////// -final class RichVectorCanStep[A](private val underlying: Vector[A]) extends AnyVal with MakesStepper[AnyStepper[A] with EfficientSubstep] { - @inline def stepper: AnyStepper[A] with EfficientSubstep = new StepsAnyVector[A](underlying, 0, underlying.length) -} - -final class RichDoubleVectorCanStep[A](private val underlying: Vector[Double]) extends AnyVal with MakesStepper[DoubleStepper with EfficientSubstep] { - @inline def stepper: DoubleStepper with EfficientSubstep = new StepsDoubleVector(underlying, 0, underlying.length) -} - -final class RichIntVectorCanStep[A](private val underlying: Vector[Int]) extends AnyVal with MakesStepper[IntStepper with EfficientSubstep] { - @inline def stepper: IntStepper with EfficientSubstep = new StepsIntVector(underlying, 0, underlying.length) -} - -final class RichLongVectorCanStep[A](private val underlying: Vector[Long]) extends AnyVal with MakesStepper[LongStepper with EfficientSubstep] { - @inline def stepper: LongStepper with EfficientSubstep = new StepsLongVector(underlying, 0, underlying.length) +final class RichVectorCanStep[T](private val underlying: Vector[T]) extends AnyVal with MakesParStepper[T] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { + case ss if ss.ref => new StepsAnyVector[T](underlying, 0, underlying.length) + case StepperShape.IntValue => new StepsIntVector (underlying.asInstanceOf[Vector[Int]], 0, underlying.length) + case StepperShape.LongValue => new StepsLongVector (underlying.asInstanceOf[Vector[Long]], 0, underlying.length) + case StepperShape.DoubleValue => new StepsDoubleVector(underlying.asInstanceOf[Vector[Double]], 0, underlying.length) + case ss => super.stepper(ss) + }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index d7efe82..d061913 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -324,7 +324,7 @@ class StepConvertersTest { @Test def comprehensivelyInt() { - implicit val spec = SpecCheck(_.isInstanceOf[IntStepper]) + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") // Int-specific tests good( co.BitSet(42).stepper ) @@ -585,7 +585,7 @@ class StepConvertersTest { @Test def comprehensivelySpecific() { - implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) _eh_( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 66997bf..26ca38c 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -6,13 +6,15 @@ import org.junit.Assert._ import java.util.stream._ import StreamConverters._ import scala.compat.java8.collectionImpl.IntStepper -import scala.compat.java8.converterImpl.{MakesStepper, MakesSequentialStream} +import scala.compat.java8.converterImpl.MakesStepper class StreamConvertersTest { def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } - + def assert(b: Boolean) { assertTrue(b) } + def assert(b: Boolean, s: String) { assertTrue(s, b) } + def arrayO(n: Int) = (1 to n).map(_.toString).toArray def arrayD(n: Int) = (1 to n).map(_.toDouble).toArray def arrayI(n: Int) = (1 to n).toArray @@ -37,7 +39,7 @@ class StreamConvertersTest { assertEq(vecO, accO.toList.toVector, s"stream $n to vector via list in parallel") assert((0 until accO.size.toInt).forall(i => vecO(i) == accO(i)), s"stream $n indexed via accumulator") assert(accO.isInstanceOf[scala.compat.java8.collectionImpl.Accumulator[_]], s"stream $n to generic accumulator") - + for (boxless <- Seq(false, true)) { val sbox = (if (boxless) "" else "(boxed)") val vecD = arrayD(n).toVector @@ -78,28 +80,28 @@ class StreamConvertersTest { } } } - + @Test def streamToScala() { for (n <- ns) { val vecO = arrayO(n).toVector assertEq(vecO, newStream(n).toScala[Vector]) assertEq(vecO, newStream(n).parallel.toScala[Vector]) - + val vecD = arrayD(n).toVector assertEq(vecD, newDoubleStream(n).toScala[Vector]) assertEq(vecD, newDoubleStream(n).parallel.toScala[Vector]) - + val vecI = arrayI(n).toVector assertEq(vecI, newIntStream(n).toScala[Vector]) assertEq(vecI, newIntStream(n).parallel.toScala[Vector]) - + val vecL = arrayL(n).toVector assertEq(vecL, newLongStream(n).toScala[Vector]) assertEq(vecL, newLongStream(n).parallel.toScala[Vector]) } } - + @Test def streamUnbox() { assert(newDoubleStream(1).boxed.unboxed.isInstanceOf[DoubleStream]) @@ -148,7 +150,7 @@ class StreamConvertersTest { assertEq(seqO, vecO.parStream.toScala[Seq]) assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) - + val arrD = arrayD(n) val seqD = arrD.toSeq val abD = abufD(n) @@ -177,7 +179,7 @@ class StreamConvertersTest { assertEq(seqD, hsD.parStream.toScala[Seq].sorted) assert(hsD.seqStream.isInstanceOf[DoubleStream]) assert(hsD.parStream.isInstanceOf[DoubleStream]) - + val arrI = arrayI(n) val seqI = arrI.toSeq val abI = abufI(n) @@ -206,7 +208,7 @@ class StreamConvertersTest { assertEq(seqI, hsI.parStream.toScala[Seq].sorted) assert(hsI.seqStream.isInstanceOf[IntStream]) assert(hsI.parStream.isInstanceOf[IntStream]) - + val arrL = arrayL(n) val seqL = arrL.toSeq val abL = abufL(n) @@ -254,9 +256,22 @@ class StreamConvertersTest { @Test def streamMaterialization(): Unit = { val coll = collection.mutable.WrappedArray.make[Int](Array(1,2,3)) - val streamize = implicitly[collection.mutable.WrappedArray[Int] => MakesSequentialStream[java.lang.Integer, IntStream]] + val streamize = implicitly[collection.mutable.WrappedArray[Int] => MakesSequentialStream[Int, IntStream]] assertTrue(streamize(coll).getClass.getName.contains("EnrichIntWrappedArrayWithStream")) - val steppize = implicitly[collection.mutable.WrappedArray[Int] => MakesStepper[IntStepper]] - assertTrue(steppize(coll).getClass.getName.contains("RichArrayIntCanStep")) + val steppize = implicitly[collection.mutable.WrappedArray[Int] => MakesStepper[Int, Any]] + assertTrue(steppize(coll).getClass.getName.contains("RichArrayCanStep")) + val stepper = steppize(coll).stepper + assertTrue(stepper.getClass.getName.contains("StepsIntArray")) + + val ss = Vector(1,2,3).seqStream + val ss2: IntStream = ss + + val coll2 = Vector(1,2,3) + val streamize2 = implicitly[Vector[Int] => MakesSequentialStream[Int, IntStream]] + assertTrue(streamize2(coll2).getClass.getName.contains("EnrichAnySteppableWithSeqStream")) + val steppize2 = implicitly[Vector[Int] => MakesStepper[Int, Any]] + assertTrue(steppize2(coll2).getClass.getName.contains("RichVectorCanStep")) + val stepper2 = steppize2(coll2).stepper + assertTrue(stepper2.getClass.getName.contains("StepsIntVector")) } } From 159000486415855fdccac7fd9fc8c96f86f2a2fc Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Wed, 20 Apr 2016 19:24:44 +0200 Subject: [PATCH 104/340] Improved StepperShape This does away with the default implementations of `MakesStepper` et. al. and moves the unboxing logic into `StepperShape` for simpler implementations with faster dispatch. --- .../compat/java8/ScalaStreamSupport.java | 2 +- .../scala/compat/java8/StreamConverters.scala | 4 +- .../java8/converterImpl/MakesSteppers.scala | 154 +++++++----------- .../java8/converterImpl/StepsArray.scala | 8 +- .../java8/converterImpl/StepsBitSet.scala | 2 +- .../converterImpl/StepsFlatHashTable.scala | 8 +- .../java8/converterImpl/StepsHashTable.scala | 37 ++--- .../java8/converterImpl/StepsImmHashMap.scala | 15 +- .../java8/converterImpl/StepsImmHashSet.scala | 8 +- .../java8/converterImpl/StepsIndexedSeq.scala | 8 +- .../java8/converterImpl/StepsIterable.scala | 8 +- .../java8/converterImpl/StepsIterator.scala | 8 +- .../java8/converterImpl/StepsLinearSeq.scala | 8 +- .../compat/java8/converterImpl/StepsMap.scala | 13 +- .../java8/converterImpl/StepsRange.scala | 12 +- .../java8/converterImpl/StepsString.scala | 4 +- .../java8/converterImpl/StepsVector.scala | 8 +- 17 files changed, 137 insertions(+), 170 deletions(-) diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java index 5afbde7..b0d3452 100644 --- a/src/main/java/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -484,7 +484,7 @@ public static IntStream intStream(scala.collection.BitSet coll) { // Let the value class figure out the casting! scala.compat.java8.converterImpl.RichBitSetCanStep rbscs = new scala.compat.java8.converterImpl.RichBitSetCanStep(coll); - return StreamSupport.intStream(rbscs.stepper(StepperShape$.MODULE$.IntValue()), false); + return StreamSupport.intStream(rbscs.stepper(StepperShape$.MODULE$.intStepperShape()), false); } /** diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index e47852d..bbb5fbd 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -21,7 +21,7 @@ sealed trait StreamShape[T, S <: BaseStream[_, S]] { def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S def fromValueStepper(mk: MakesKeyValueStepper[_, T, _], par: Boolean): S } -object StreamShape extends StreamShapeLowPrio { +object StreamShape extends StreamShapeLowPriority { // primitive implicit val IntValue = intStreamShape[Int] implicit val LongValue = longStreamShape[Long] @@ -33,7 +33,7 @@ object StreamShape extends StreamShapeLowPrio { implicit val CharValue = intStreamShape[Char] implicit val FloatValue = doubleStreamShape[Float] } -trait StreamShapeLowPrio { +trait StreamShapeLowPriority { protected[this] abstract class BaseStreamShape[T, S <: BaseStream[_, S], St <: Stepper[_]](implicit ss: StepperShape[T, St]) extends StreamShape[T, S] { final def fromStepper (mk: MakesStepper[T, _], par: Boolean): S = stream(mk.stepper, par) final def fromKeyStepper (mk: MakesKeyValueStepper[T, _, _], par: Boolean): S = stream(mk.keyStepper, par) diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index 1079d24..017f2cd 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -18,104 +18,76 @@ trait MakesKeyValueStepper[K, V, +Extra] extends Any { def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]): S with Extra } -sealed trait StepperShape[T, S <: Stepper[_]] { def ref: Boolean } -object StepperShape extends StepperShapeLowPrio { - private[this] def valueShape[T, S <: Stepper[_]]: StepperShape[T, S] = new StepperShape[T, S] { def ref = false } +/** Encodes the translation from an element type `T` to the corresponding Stepper type `S` */ +sealed trait StepperShape[T, S <: Stepper[_]] { + /** Return the Int constant (as defined in the `StepperShape` companion object) for this `StepperShape`. */ + def shape: Int - // primitive - implicit val IntValue = valueShape[Int, IntStepper] - implicit val LongValue = valueShape[Long, LongStepper] - implicit val DoubleValue = valueShape[Double, DoubleStepper] + /** Create an unboxing primitive sequential Stepper from a boxed `AnyStepper`. + * This is an identity operation for reference shapes. */ + def seqUnbox(st: AnyStepper[T]): S - // widening - implicit val ByteValue = valueShape[Byte, IntStepper] - implicit val ShortValue = valueShape[Short, IntStepper] - implicit val CharValue = valueShape[Char, IntStepper] - implicit val FloatValue = valueShape[Float, DoubleStepper] + /** Create an unboxing primitive parallel (i.e. `with EfficientSubstep`) Stepper from a boxed `AnyStepper`. + * This is an identity operation for reference shapes. */ + def parUnbox(st: AnyStepper[T] with EfficientSubstep): S with EfficientSubstep } -trait StepperShapeLowPrio { +object StepperShape extends StepperShapeLowPriority { // reference - implicit def anyStepperShape[T]: StepperShape[T, AnyStepper[T]] = new StepperShape[T, AnyStepper[T]] { def ref = true } -} - -/** Superclass for `MakesStepper` implementations which support parallelization. At least the `AnyStepper` case must be - * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ -trait MakesParStepper[T] extends Any with MakesStepper[T, EfficientSubstep] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep - case _ => throw new NotImplementedError("AnyStepper must be handled in `stepper` implementations") - }).asInstanceOf[S with EfficientSubstep] -} + final val Reference = 0 -/** Superclass for `MakesStepper` implementations which do not support parallelization. At least the `AnyStepper` case must be - * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ -trait MakesSeqStepper[T] extends Any with MakesStepper[T, Any] { - def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Int ]]) - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Long ]]) - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Double]]) - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Byte ]]) - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Short ]]) - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Char ]]) - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (stepper(StepperShape.anyStepperShape[T]).asInstanceOf[AnyStepper[Float ]]) - case _ => throw new NotImplementedError("AnyStepper must be handled in `stepper` implementations") - }).asInstanceOf[S] -} + // primitive + final val IntValue = 1 + final val LongValue = 2 + final val DoubleValue = 3 -/** Superclass for `MakesKeyalueStepper` implementations which support parallelization. At least the `AnyStepper` case must be - * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ -trait MakesKeyValueParStepper[K, V] extends Any with MakesKeyValueStepper[K, V, EfficientSubstep] { - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep - case _ => throw new NotImplementedError("AnyStepper case must be handled in `keyStepper` implementations") - }).asInstanceOf[S with EfficientSubstep] + // widening + final val ByteValue = 4 + final val ShortValue = 5 + final val CharValue = 6 + final val FloatValue = 7 - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Int ]]) with EfficientSubstep - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Long ]]) with EfficientSubstep - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Double]]) with EfficientSubstep - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Byte ]]) with EfficientSubstep - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Short ]]) with EfficientSubstep - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Char ]]) with EfficientSubstep - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Float ]]) with EfficientSubstep - case _ => throw new NotImplementedError("AnyStepper case must be handled in `valueStepper` implementations") - }).asInstanceOf[S with EfficientSubstep] + implicit val intStepperShape: StepperShape[Int, IntStepper] = new StepperShape[Int, IntStepper] { + def shape = IntValue + def seqUnbox(st: AnyStepper[Int]): IntStepper = new Stepper.UnboxingIntStepper(st) + def parUnbox(st: AnyStepper[Int] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingIntStepper(st) with EfficientSubstep + } + implicit val longStepperShape: StepperShape[Long, LongStepper] = new StepperShape[Long, LongStepper] { + def shape = LongValue + def seqUnbox(st: AnyStepper[Long]): LongStepper = new Stepper.UnboxingLongStepper(st) + def parUnbox(st: AnyStepper[Long] with EfficientSubstep): LongStepper with EfficientSubstep = new Stepper.UnboxingLongStepper(st) with EfficientSubstep + } + implicit val doubleStepperShape: StepperShape[Double, DoubleStepper] = new StepperShape[Double, DoubleStepper] { + def shape = DoubleValue + def seqUnbox(st: AnyStepper[Double]): DoubleStepper = new Stepper.UnboxingDoubleStepper(st) + def parUnbox(st: AnyStepper[Double] with EfficientSubstep): DoubleStepper with EfficientSubstep = new Stepper.UnboxingDoubleStepper(st) with EfficientSubstep + } + implicit val byteStepperShape: StepperShape[Byte, IntStepper] = new StepperShape[Byte, IntStepper] { + def shape = ByteValue + def seqUnbox(st: AnyStepper[Byte]): IntStepper = new Stepper.UnboxingByteStepper(st) + def parUnbox(st: AnyStepper[Byte] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingByteStepper(st) with EfficientSubstep + } + implicit val shortStepperShape: StepperShape[Short, IntStepper] = new StepperShape[Short, IntStepper] { + def shape = ShortValue + def seqUnbox(st: AnyStepper[Short]): IntStepper = new Stepper.UnboxingShortStepper(st) + def parUnbox(st: AnyStepper[Short] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingShortStepper(st) with EfficientSubstep + } + implicit val charStepperShape: StepperShape[Char, IntStepper] = new StepperShape[Char, IntStepper] { + def shape = CharValue + def seqUnbox(st: AnyStepper[Char]): IntStepper = new Stepper.UnboxingCharStepper(st) + def parUnbox(st: AnyStepper[Char] with EfficientSubstep): IntStepper with EfficientSubstep = new Stepper.UnboxingCharStepper(st) with EfficientSubstep + } + implicit val floatStepperShape: StepperShape[Float, DoubleStepper] = new StepperShape[Float, DoubleStepper] { + def shape = FloatValue + def seqUnbox(st: AnyStepper[Float]): DoubleStepper = new Stepper.UnboxingFloatStepper(st) + def parUnbox(st: AnyStepper[Float] with EfficientSubstep): DoubleStepper with EfficientSubstep = new Stepper.UnboxingFloatStepper(st) with EfficientSubstep + } } +trait StepperShapeLowPriority { + implicit def anyStepperShape[T] = anyStepperShapePrototype.asInstanceOf[StepperShape[T, AnyStepper[T]]] -/** Superclass for `MakesKeyalueStepper` implementations which do not support parallelization. At least the `AnyStepper` case must be - * implemented, all others default to building an `AnyStepper` and putting an unboxing conversion on top. */ -trait MakesKeyValueSeqStepper[K, V] extends Any with MakesKeyValueStepper[K, V, Any] { - def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Int ]]) - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Long ]]) - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Double]]) - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Byte ]]) - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Short ]]) - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Char ]]) - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (keyStepper(StepperShape.anyStepperShape[K]).asInstanceOf[AnyStepper[Float ]]) - case _ => throw new NotImplementedError("AnyStepper case must be handled in `keyStepper` implementations") - }).asInstanceOf[S] - - def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { - case StepperShape.IntValue => new Stepper.UnboxingIntStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Int ]]) - case StepperShape.LongValue => new Stepper.UnboxingLongStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Long ]]) - case StepperShape.DoubleValue => new Stepper.UnboxingDoubleStepper(valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Double]]) - case StepperShape.ByteValue => new Stepper.UnboxingByteStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Byte ]]) - case StepperShape.ShortValue => new Stepper.UnboxingShortStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Short ]]) - case StepperShape.CharValue => new Stepper.UnboxingCharStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Char ]]) - case StepperShape.FloatValue => new Stepper.UnboxingFloatStepper (valueStepper(StepperShape.anyStepperShape[V]).asInstanceOf[AnyStepper[Float ]]) - case _ => throw new NotImplementedError("AnyStepper case must be handled in `valueStepper` implementations") - }).asInstanceOf[S] + private[this] val anyStepperShapePrototype: StepperShape[AnyRef, AnyStepper[AnyRef]] = new StepperShape[AnyRef, AnyStepper[AnyRef]] { + def shape = StepperShape.Reference + def seqUnbox(st: AnyStepper[AnyRef]): AnyStepper[AnyRef] = st + def parUnbox(st: AnyStepper[AnyRef] with EfficientSubstep): AnyStepper[AnyRef] with EfficientSubstep = st + } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index 0da150e..ef75eb6 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -69,9 +70,9 @@ extends StepsLongLikeIndexed[StepsLongArray](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichArrayCanStep[T](private val underlying: Array[T]) extends AnyVal with MakesParStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => +final class RichArrayCanStep[T](private val underlying: Array[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { + case StepperShape.Reference => if(underlying.isInstanceOf[Array[Boolean]]) new StepsBoxedBooleanArray (underlying.asInstanceOf[Array[Boolean]], 0, underlying.length) else new StepsObjectArray[AnyRef](underlying.asInstanceOf[Array[AnyRef ]], 0, underlying.length) @@ -82,6 +83,5 @@ final class RichArrayCanStep[T](private val underlying: Array[T]) extends AnyVal case StepperShape.ShortValue => new StepsWidenedShortArray (underlying.asInstanceOf[Array[Short ]], 0, underlying.length) case StepperShape.CharValue => new StepsWidenedCharArray (underlying.asInstanceOf[Array[Char ]], 0, underlying.length) case StepperShape.FloatValue => new StepsWidenedFloatArray (underlying.asInstanceOf[Array[Float ]], 0, underlying.length) - case ss => super.stepper(ss) }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala index 55bae9f..b6f698a 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -53,7 +53,7 @@ extends StepsIntLikeSliced[Array[Long], StepsIntBitSet](_underlying, _i0, _iN) { // Value class adapter // ///////////////////////// -final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesParStepper[Int] { +final class RichBitSetCanStep(private val underlying: collection.BitSet) extends AnyVal with MakesStepper[Int, EfficientSubstep] { override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = { val bits: Array[Long] = underlying match { case m: collection.mutable.BitSet => CollectionInternals.getBitSetInternals(m) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index 70dbc76..ec30008 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -39,15 +40,14 @@ extends StepsLongLikeGapped[StepsLongFlatHashTable](_underlying, _i0, _iN) { // Value class adapters // ////////////////////////// -final class RichFlatHashTableCanStep[T](private val underlying: collection.mutable.FlatHashTable[T]) extends AnyVal with MakesParStepper[T] { +final class RichFlatHashTableCanStep[T](private val underlying: collection.mutable.FlatHashTable[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = { val tbl = CollectionInternals.getTable(underlying) - (ss match { - case ss if ss.ref => new StepsAnyFlatHashTable[T](tbl, 0, tbl.length) + ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntFlatHashTable (tbl, 0, tbl.length) case StepperShape.LongValue => new StepsLongFlatHashTable (tbl, 0, tbl.length) case StepperShape.DoubleValue => new StepsDoubleFlatHashTable(tbl, 0, tbl.length) - case ss => super.stepper(ss) + case _ => ss.parUnbox(new StepsAnyFlatHashTable[T](tbl, 0, tbl.length)) }).asInstanceOf[S with EfficientSubstep] } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala index 4a328d1..dde431e 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -140,62 +141,58 @@ extends StepsLongLikeGapped[StepsLongLinkedHashTableValue[K]](_underlying.asInst // Steppers for entries stored in DefaultEntry HashEntry -final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { +final class RichDefaultHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.DefaultEntry[K, V]]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) new StepsAnyDefaultHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] } - override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - (ss match { - case ss if ss.ref => new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length) + ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) - case ss => super.keyStepper(ss) + case _ => ss.parUnbox(new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length)) }).asInstanceOf[S with EfficientSubstep] } - override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.DefaultEntry[K, V]](underlying) - (ss match { - case ss if ss.ref => new StepsAnyDefaultHashTableValue (tbl, 0, tbl.length) + ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Int ]]]], 0, tbl.length) case StepperShape.LongValue => new StepsLongDefaultHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Long ]]]], 0, tbl.length) case StepperShape.DoubleValue => new StepsDoubleDefaultHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.DefaultEntry[K, Double]]]], 0, tbl.length) - case ss => super.valueStepper(ss) + case _ => ss.parUnbox(new StepsAnyDefaultHashTableValue (tbl, 0, tbl.length)) }).asInstanceOf[S with EfficientSubstep] } } // Steppers for entries stored in LinkedEntry HashEntry -final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { +final class RichLinkedHashTableCanStep[K, V](private val underlying: collection.mutable.HashTable[K, collection.mutable.LinkedEntry[K, V]]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) new StepsAnyLinkedHashTable(tbl, 0, tbl.length).asInstanceOf[S with EfficientSubstep] } - override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - (ss match { - case ss if ss.ref => new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length) + ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Int, _]]], 0, tbl.length) case StepperShape.LongValue => new StepsLongHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[Long, _]]], 0, tbl.length) case StepperShape.DoubleValue => new StepsDoubleHashTableKey(tbl.asInstanceOf[Array[collection.mutable.HashEntry[Double, _]]], 0, tbl.length) - case ss => super.keyStepper(ss) + case _ => ss.parUnbox(new StepsAnyHashTableKey (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, _]]], 0, tbl.length)) }).asInstanceOf[S with EfficientSubstep] } - override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = { val tbl = CollectionInternals.getTable[K, collection.mutable.LinkedEntry[K, V]](underlying) - (ss match { - case ss if ss.ref => new StepsAnyLinkedHashTableValue (tbl, 0, tbl.length) + ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Int ]]]], 0, tbl.length) case StepperShape.LongValue => new StepsLongLinkedHashTableValue (tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Long ]]]], 0, tbl.length) case StepperShape.DoubleValue => new StepsDoubleLinkedHashTableValue(tbl.asInstanceOf[Array[collection.mutable.HashEntry[K, collection.mutable.LinkedEntry[K, Double]]]], 0, tbl.length) - case ss => super.valueStepper(ss) + case _ => ss.parUnbox(new StepsAnyLinkedHashTableValue (tbl, 0, tbl.length)) }).asInstanceOf[S with EfficientSubstep] } } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala index 888c1d4..d6a5b0e 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -125,23 +126,21 @@ extends StepsLongLikeImmHashMap[K, Long, StepsLongImmHashMapValue[K]](_underlyin // Value class adapters // ////////////////////////// -final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal with MakesKeyValueParStepper[K, V] with MakesParStepper[(K, V)] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = +final class RichImmHashMapCanStep[K, V](private val underlying: collection.immutable.HashMap[K, V]) extends AnyVal with MakesKeyValueStepper[K, V, EfficientSubstep] with MakesStepper[(K, V), EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[(K, V), S]) = new StepsAnyImmHashMap[K, V](underlying, 0, underlying.size).asInstanceOf[S with EfficientSubstep] - override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { - case ss if ss.ref => new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size) + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Int, V]], 0, underlying.size) case StepperShape.LongValue => new StepsLongImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Long, V]], 0, underlying.size) case StepperShape.DoubleValue => new StepsDoubleImmHashMapKey (underlying.asInstanceOf[collection.immutable.HashMap[Double, V]], 0, underlying.size) - case ss => super.keyStepper(ss) + case _ => ss.parUnbox(new StepsAnyImmHashMapKey[K, V](underlying, 0, underlying.size)) }).asInstanceOf[S with EfficientSubstep] - override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { - case ss if ss.ref => new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size) + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Int]], 0, underlying.size) case StepperShape.LongValue => new StepsLongImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Long]], 0, underlying.size) case StepperShape.DoubleValue => new StepsDoubleImmHashMapValue (underlying.asInstanceOf[collection.immutable.HashMap[K, Double]], 0, underlying.size) - case ss => super.valueStepper(ss) + case _ => ss.parUnbox(new StepsAnyImmHashMapValue[K, V](underlying, 0, underlying.size)) }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala index 56e0560..abde687 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -39,12 +40,11 @@ extends StepsLongLikeTrieIterator[StepsLongImmHashSet](_underlying, _N) { // Value class adapters // ////////////////////////// -final class RichImmHashSetCanStep[T](private val underlying: collection.immutable.HashSet[T]) extends AnyVal with MakesParStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyImmHashSet[T](underlying.iterator, underlying.size) +final class RichImmHashSetCanStep[T](private val underlying: collection.immutable.HashSet[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntImmHashSet (underlying.iterator.asInstanceOf[Iterator[Int]], underlying.size) case StepperShape.LongValue => new StepsLongImmHashSet (underlying.iterator.asInstanceOf[Iterator[Long]], underlying.size) case StepperShape.DoubleValue => new StepsDoubleImmHashSet(underlying.iterator.asInstanceOf[Iterator[Double]], underlying.size) - case ss => super.stepper(ss) + case _ => ss.parUnbox(new StepsAnyImmHashSet[T](underlying.iterator, underlying.size)) }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index 69d3260..e36fab0 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -39,12 +40,11 @@ extends StepsLongLikeIndexed[StepsLongIndexedSeq[CC]](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichIndexedSeqCanStep[T](private val underlying: collection.IndexedSeqLike[T, _]) extends AnyVal with MakesParStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyIndexedSeq[T](underlying, 0, underlying.length) +final class RichIndexedSeqCanStep[T](private val underlying: collection.IndexedSeqLike[T, _]) extends AnyVal with MakesStepper[T, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Int, _]], 0, underlying.length) case StepperShape.LongValue => new StepsLongIndexedSeq (underlying.asInstanceOf[collection.IndexedSeqLike[Long, _]], 0, underlying.length) case StepperShape.DoubleValue => new StepsDoubleIndexedSeq(underlying.asInstanceOf[collection.IndexedSeqLike[Double, _]], 0, underlying.length) - case ss => super.stepper(ss) + case _ => ss.parUnbox(new StepsAnyIndexedSeq[T](underlying, 0, underlying.length)) }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala index 256d121..dd8d6a3 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -10,12 +11,11 @@ import Stepper._ // Iterables just defer to iterator unless they can pattern match something better. // TODO: implement pattern matching! -final class RichIterableCanStep[T](private val underlying: Iterable[T]) extends AnyVal with MakesSeqStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyIterator[T](underlying.iterator) +final class RichIterableCanStep[T](private val underlying: Iterable[T]) extends AnyVal with MakesStepper[T, Any] { + override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntIterator (underlying.iterator.asInstanceOf[Iterator[Int]]) case StepperShape.LongValue => new StepsLongIterator (underlying.iterator.asInstanceOf[Iterator[Long]]) case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.iterator.asInstanceOf[Iterator[Double]]) - case ss => super.stepper(ss) + case _ => ss.seqUnbox(new StepsAnyIterator[T](underlying.iterator)) }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala index 5058303..02f58cd 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -39,12 +40,11 @@ extends StepsLongLikeIterator[StepsLongIterator](_underlying) { // Value class adapters // ////////////////////////// -final class RichIteratorCanStep[T](private val underlying: Iterator[T]) extends AnyVal with MakesSeqStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyIterator[T](underlying) +final class RichIteratorCanStep[T](private val underlying: Iterator[T]) extends AnyVal with MakesStepper[T, Any] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntIterator (underlying.asInstanceOf[Iterator[Int]]) case StepperShape.LongValue => new StepsLongIterator (underlying.asInstanceOf[Iterator[Long]]) case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.asInstanceOf[Iterator[Double]]) - case ss => super.stepper(ss) + case _ => ss.seqUnbox(new StepsAnyIterator[T](underlying)) }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index c111915..892bed5 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -47,12 +48,11 @@ extends StepsLongWithTail[collection.LinearSeq[Long], StepsLongLinearSeq](_under // Value class adapters // ////////////////////////// -final class RichLinearSeqCanStep[T](private val underlying: collection.LinearSeq[T]) extends AnyVal with MakesSeqStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyLinearSeq[T](underlying, Long.MaxValue) +final class RichLinearSeqCanStep[T](private val underlying: collection.LinearSeq[T]) extends AnyVal with MakesStepper[T, Any] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Int]], Long.MaxValue) case StepperShape.LongValue => new StepsLongLinearSeq (underlying.asInstanceOf[collection.LinearSeq[Long]], Long.MaxValue) case StepperShape.DoubleValue => new StepsDoubleLinearSeq(underlying.asInstanceOf[collection.LinearSeq[Double]], Long.MaxValue) - case ss => super.stepper(ss) + case _ => ss.seqUnbox(new StepsAnyLinearSeq[T](underlying, Long.MaxValue)) }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index d5ae3bb..3a1f49c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -10,22 +11,20 @@ import Stepper._ // Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching // TODO: implement pattern matching -final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyValueSeqStepper[K, V] { +final class RichMapCanStep[K, V](private val underlying: collection.Map[K, V]) extends AnyVal with MakesKeyValueStepper[K, V, Any] { // No generic stepper because RichIterableCanStep will get that anyway, and we don't pattern match here - override def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = (ss match { - case ss if ss.ref => new StepsAnyIterator (underlying.keysIterator) + def keyStepper[S <: Stepper[_]](implicit ss: StepperShape[K, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntIterator (underlying.keysIterator.asInstanceOf[Iterator[Int]]) case StepperShape.LongValue => new StepsLongIterator (underlying.keysIterator.asInstanceOf[Iterator[Long]]) case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.keysIterator.asInstanceOf[Iterator[Double]]) - case ss => super.keyStepper(ss) + case _ => ss.seqUnbox(new StepsAnyIterator (underlying.keysIterator)) }).asInstanceOf[S] - override def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = (ss match { - case ss if ss.ref => new StepsAnyIterator (underlying.valuesIterator) + def valueStepper[S <: Stepper[_]](implicit ss: StepperShape[V, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntIterator (underlying.valuesIterator.asInstanceOf[Iterator[Int]]) case StepperShape.LongValue => new StepsLongIterator (underlying.valuesIterator.asInstanceOf[Iterator[Long]]) case StepperShape.DoubleValue => new StepsDoubleIterator(underlying.valuesIterator.asInstanceOf[Iterator[Double]]) - case ss => super.valueStepper(ss) + case _ => ss.seqUnbox(new StepsAnyIterator (underlying.valuesIterator)) }).asInstanceOf[S] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index 4dc0eec..63505c8 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -39,16 +40,15 @@ extends StepsLongLikeIndexed[StepsLongNumericRange](_i0, _iN) { // Value class adapters // ////////////////////////// -final class RichRangeCanStep[T](private val underlying: Range) extends AnyVal with MakesParStepper[Int] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = +final class RichRangeCanStep[T](private val underlying: Range) extends AnyVal with MakesStepper[Int, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[Int, S]) = new StepsIntRange(underlying, 0, underlying.length).asInstanceOf[S with EfficientSubstep] } -final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesParStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyNumericRange[T](underlying, 0, underlying.length) +final class RichNumericRangeCanStep[T](private val underlying: collection.immutable.NumericRange[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Int]], 0, underlying.length) case StepperShape.LongValue => new StepsLongNumericRange (underlying.asInstanceOf[collection.immutable.NumericRange[Long]], 0, underlying.length) - case ss => super.stepper(ss) + case _ => ss.parUnbox(new StepsAnyNumericRange[T](underlying, 0, underlying.length)) }).asInstanceOf[S with EfficientSubstep] } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index 85e4706..c8c7ad6 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -45,8 +45,8 @@ private[java8] class StepperStringCodePoint(underlying: String, var i0: Int, var // Value class adapter // ///////////////////////// -final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesParStepper[Char] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[Char, S]) = charStepper.asInstanceOf[S with EfficientSubstep] +final class RichStringCanStep(private val underlying: String) extends AnyVal with MakesStepper[Char, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[Char, S]) = charStepper.asInstanceOf[S with EfficientSubstep] @inline def charStepper: IntStepper with EfficientSubstep = new StepperStringChar(underlying, 0, underlying.length) @inline def codepointStepper: IntStepper with EfficientSubstep = new StepperStringCodePoint(underlying, 0, underlying.length) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index 046a587..ad54503 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,6 +1,7 @@ package scala.compat.java8.converterImpl import language.implicitConversions +import scala.annotation.switch import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -134,12 +135,11 @@ with StepsVectorLike[Long] { // Value class adapters // ////////////////////////// -final class RichVectorCanStep[T](private val underlying: Vector[T]) extends AnyVal with MakesParStepper[T] { - override def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = (ss match { - case ss if ss.ref => new StepsAnyVector[T](underlying, 0, underlying.length) +final class RichVectorCanStep[T](private val underlying: Vector[T]) extends AnyVal with MakesStepper[T, EfficientSubstep] { + def stepper[S <: Stepper[_]](implicit ss: StepperShape[T, S]) = ((ss.shape: @switch) match { case StepperShape.IntValue => new StepsIntVector (underlying.asInstanceOf[Vector[Int]], 0, underlying.length) case StepperShape.LongValue => new StepsLongVector (underlying.asInstanceOf[Vector[Long]], 0, underlying.length) case StepperShape.DoubleValue => new StepsDoubleVector(underlying.asInstanceOf[Vector[Double]], 0, underlying.length) - case ss => super.stepper(ss) + case _ => ss.parUnbox(new StepsAnyVector[T](underlying, 0, underlying.length)) }).asInstanceOf[S with EfficientSubstep] } From 8369f39743be1dc4bc9b64ad77a87ea8e8d33ec4 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 4 Jul 2016 14:24:04 +0200 Subject: [PATCH 105/340] Support Scala 2.12.0-M5 --- .travis.yml | 2 +- build.sbt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b73bc89..4eeb932 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - admin/build.sh scala: - 2.11.8 - - 2.12.0-M4 + - 2.12.0-M5 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index 8de068f..9b06450 100644 --- a/build.sbt +++ b/build.sbt @@ -10,7 +10,7 @@ def jwrite(dir: java.io.File)(name: String, content: String) = { lazy val commonSettings = Seq( scalaVersion := "2.11.8", - crossScalaVersions := List("2.11.8", "2.12.0-M4"), + crossScalaVersions := List("2.11.8", "2.12.0-M5"), organization := "org.scala-lang.modules", version := "0.8.0-SNAPSHOT" ) @@ -102,7 +102,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.9" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From 4a4f5387316ce99403d4b4810cd8b0f17bb11c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Bi=C5=82as?= Date: Tue, 23 Aug 2016 16:48:10 +0200 Subject: [PATCH 106/340] StreamConverters: correct typo in ScalaDoc StreamConverers -> StreamConverters --- src/main/scala/scala/compat/java8/StreamConverters.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index bbb5fbd..c6334a2 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -159,7 +159,7 @@ trait Priority1StreamConverters extends Priority2StreamConverters { * * Examples: * {{{ - * import scala.compat.java8.StreamConverers._ + * import scala.compat.java8.StreamConverters._ * * val s = Vector(1,2,3,4).parStream // Stream[Int] * val si = s.unboxed // Stream.OfInt From c7bf67bd22357d831011ec6832ca1f48d0fb9d6f Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Mon, 29 Aug 2016 20:41:21 +0200 Subject: [PATCH 107/340] Provide compatibility with current Scala 2.12.x (close to RC1) - Add the required `override` modifiers to trait methods that now extend default methods of Java interfaces. - Add casts in some of these methods because the Scala primitive types are not compatible at the type level with the (now inherited) Java boxed types. - Use the boxed JFunction types in BoxingTest because the generic ones do not exist anymore. - Tests in LambdaTest need to be commented out because usage from Java changed significantly after https://github.com/scala/scala/pull/5298 but we can still cross-build the actual library against 2.11 and 2.12.0-M5. At some point we should consider branching. --- .../java8/PrimitiveIteratorConversions.scala | 24 +++--- .../compat/java8/collectionImpl/Stepper.scala | 20 ++--- .../java/scala/runtime/java8/BoxingTest.java | 4 +- .../java/scala/runtime/java8/LambdaTest.java | 79 +++++++------------ .../runtime/java8/SpecializedFactoryTest.java | 20 ----- 5 files changed, 54 insertions(+), 93 deletions(-) delete mode 100644 src/test/java/scala/runtime/java8/SpecializedFactoryTest.java diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 3e0a10b..da991c2 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -41,13 +41,13 @@ object PrimitiveIteratorConverters { /** Packages a `scala.collection.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ def fromScala(it: Iterator[Double]): PrimitiveIterator.OfDouble = new PrimitiveIterator.OfDouble { def hasNext = it.hasNext - def next() = it.next() + override def next() = it.next().asInstanceOf[java.lang.Double] def nextDouble() = it.next() - def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { + override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (it.hasNext) c.accept(it.next) } - def forEachRemaining(c: java.util.function.DoubleConsumer) { + override def forEachRemaining(c: java.util.function.DoubleConsumer) { while (it.hasNext) c.accept(it.next) } } @@ -62,13 +62,13 @@ object PrimitiveIteratorConverters { /** Packages a `scala.collection.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ def fromScala(it: Iterator[Int]): PrimitiveIterator.OfInt = new PrimitiveIterator.OfInt { def hasNext = it.hasNext - def next() = it.next() + override def next() = it.next().asInstanceOf[java.lang.Integer] def nextInt() = it.next() - def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { + override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (it.hasNext) c.accept(it.next) } - def forEachRemaining(c: java.util.function.IntConsumer) { + override def forEachRemaining(c: java.util.function.IntConsumer) { while (it.hasNext) c.accept(it.next) } } @@ -83,13 +83,13 @@ object PrimitiveIteratorConverters { /** Packages a `scala.collection.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ def fromScala(it: Iterator[Long]): PrimitiveIterator.OfLong = new PrimitiveIterator.OfLong { def hasNext = it.hasNext - def next() = it.next() + override def next() = it.next().asInstanceOf[java.lang.Long] def nextLong() = it.next() - def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { + override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (it.hasNext) c.accept(it.next) } - def forEachRemaining(c: java.util.function.LongConsumer) { + override def forEachRemaining(c: java.util.function.LongConsumer) { while (it.hasNext) c.accept(it.next) } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index 1ca95dd..aa9d6cd 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -227,7 +227,7 @@ private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterator[A] with StepperLike[A, AnyStepper[A]] { - def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = next @@ -267,12 +267,12 @@ private[collectionImpl] object AnyStepper { /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } - def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + override def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextDouble - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false + override def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Double]): Boolean = if (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)); true } else false def tryAdvance(c: java.util.function.DoubleConsumer): Boolean = if (hasNext) { c.accept(nextDouble); true } else false def tryStep(f: Double => Unit): Boolean = if (hasNext) { f(nextDouble); true } else false def trySplit() = substep @@ -283,12 +283,12 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt with StepperLike[Int, IntStepper] { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } - def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + override def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextInt - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false + override def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Integer]): Boolean = if (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)); true } else false def tryAdvance(c: java.util.function.IntConsumer): Boolean = if (hasNext) { c.accept(nextInt); true } else false def tryStep(f: Int => Unit): Boolean = if (hasNext) { f(nextInt); true } else false def trySplit() = substep @@ -299,12 +299,12 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong with StepperLike[Long, LongStepper] { - def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } - def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + override def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextLong - def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false + override def tryAdvance(c: java.util.function.Consumer[_ >: java.lang.Long]): Boolean = if (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)); true } else false def tryAdvance(c: java.util.function.LongConsumer): Boolean = if (hasNext) { c.accept(nextLong); true } else false def tryStep(f: Long => Unit): Boolean = if (hasNext) { f(nextLong); true } else false def trySplit() = substep diff --git a/src/test/java/scala/runtime/java8/BoxingTest.java b/src/test/java/scala/runtime/java8/BoxingTest.java index f4e6da6..083b5de 100644 --- a/src/test/java/scala/runtime/java8/BoxingTest.java +++ b/src/test/java/scala/runtime/java8/BoxingTest.java @@ -8,7 +8,7 @@ public class BoxingTest { @Test public void nullBoxesInterpretedAsZeroF1() { - JFunction1 jFunction1 = new JFunction1$mcII$sp() { + JFunction1$mcII$sp jFunction1 = new JFunction1$mcII$sp() { @Override public int apply$mcII$sp(int v1) { return v1 + 1; @@ -20,7 +20,7 @@ public void nullBoxesInterpretedAsZeroF1() { @Test public void nullBoxesInterpretedAsZeroF2() { - JFunction2 jFunction2 = new JFunction2$mcIII$sp() { + JFunction2$mcIII$sp jFunction2 = new JFunction2$mcIII$sp() { @Override public int apply$mcIII$sp(int v1, int v2) { return v1 + v2 + 1; diff --git a/src/test/java/scala/runtime/java8/LambdaTest.java b/src/test/java/scala/runtime/java8/LambdaTest.java index 7d9f7b7..9d67926 100644 --- a/src/test/java/scala/runtime/java8/LambdaTest.java +++ b/src/test/java/scala/runtime/java8/LambdaTest.java @@ -7,32 +7,20 @@ import scala.runtime.*; import static junit.framework.Assert.assertEquals; -import static scala.runtime.java8.JFunction.*; import static scala.runtime.java8.TestAPI.*; import org.junit.Test; public class LambdaTest { + /* + // This version is for Scala 2.12.0-RC1 and is not compatible with 2.11. It's commented out to allow cross-building. @Test public void lambdaDemo() { - // Not allowed with Scala 2.10 nor 2.11 - // "incompatible types: Function1 is not a functional interface" - // scala.Function1 f = (String s) -> s; - - // Function1 is not a functional interface because it has abstract - // methods in addition to apply, namely `compose` and `andThen` - // (which are implemented in Scala-derived subclasses with mixin - // inheritance), and the specialized variants of apply (also provided - // by scalac.) - - // That's a pity, but we can get pretty close with this library! - - // We have to tell javac to use `JFunction1` as the functional interface. - JFunction1 f1 = (String s) -> s; + scala.Function1 f1 = (String s) -> s; // That's more or less equivalent to the old, anonymous class syntax: - new JFunction1() { + new scala.Function1() { public String apply(String s) { return s; } }; @@ -47,80 +35,73 @@ public void lambdaDemo() { // F1 is a subclass of Function1: scala.Function1 f2 = f1; - // Factory methods in `JFunction` can reduce the verbosity a little: - // `func` is actually just an identity method; it only exists to - // trigger lambda creation using the `JFunction1` functional interface. - scala.Function1 f3 = func((String s) -> s); - - // Note that javac's type inference can infer the parameter type here, - // based on the acribed type of `f4`. - scala.Function1 f4 = func(s -> s); - - // f1.apply(""); + scala.Function1 f3 = (String s) -> s; + scala.Function1 f4 = s -> s; // Specialized variants of the `apply` method are implenented in the // functional interface - JFunction1 f5 = (i) -> -i; + scala.Function1 f5 = (i -> -i); assert(f5.apply(1) == -1); assert(f5.apply$mcII$sp(1) == -1); // as are `curried`, `tupled`, `compose`, `andThen`. f3.compose(f3).andThen(f3).apply(""); - scala.Function2 f6 = func((s1, s2) -> join(s1, s2)); + scala.Function2 f6 = ((s1, s2) -> join(s1, s2)); assert(f6.curried().apply("1").apply("2").equals("12")); - // Functions returning unit must use the `JProcedure1`, ... functional interfaces - // in order to convert a void lamdba return to Scala's Unit. - // - // The easiest way to do this is via `JFunction.proc`, .... + // Functions returning unit must return BoxedUnit.UNIT explicitly. // // Note that the lambda has a return type of `void` if the last // statement is a call to a `void` returning method, or if it is // a `return`. - scala.Function1 f7 = proc(s -> sideEffect()); - scala.Function1 f8 = proc(s -> {s.toUpperCase(); return;}); + scala.Function1 f7 = (s -> { sideEffect(); return scala.runtime.BoxedUnit.UNIT; }); + scala.Function1 f8 = (s -> { s.toUpperCase(); return scala.runtime.BoxedUnit.UNIT; }); // Function0 is also available - scala.Function0 f9 = func(() -> "42"); + scala.Function0 f9 = (() -> "42"); assert(f9.apply().equals("42")); // You can go up to 22 (the highest arity function defined in the Scala standard library.) - assert(acceptFunction1(func(v1 -> v1.toUpperCase())).equals("1")); - acceptFunction1Unit(proc(v1 -> sideEffect())); - acceptFunction1Unit(proc(v1 -> {v1.toUpperCase(); return;})); + assert(acceptFunction1((v1 -> v1.toUpperCase())).equals("1")); + acceptFunction1Unit((v1 -> {sideEffect(); return scala.runtime.BoxedUnit.UNIT;})); + acceptFunction1Unit((v1 -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - assert(acceptFunction2(func((v1, v2) -> join(v1, v2))).equals("12")); - acceptFunction2Unit(proc((v1, v2) -> {v1.toUpperCase(); return;})); + assert(acceptFunction2(((v1, v2) -> join(v1, v2))).equals("12")); + acceptFunction2Unit(((v1, v2) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - assert(acceptFunction3(func((v1, v2, v3) -> join(v1, v2, v3))).equals("123")); - acceptFunction3Unit(proc((v1, v2, v3) -> {v1.toUpperCase(); return;})); + assert(acceptFunction3(((v1, v2, v3) -> join(v1, v2, v3))).equals("123")); + acceptFunction3Unit(((v1, v2, v3) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - assert(acceptFunction22(func((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> join(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22))).equals("12345678910111213141516171819202122")); - acceptFunction22Unit( proc((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return;})); + assert(acceptFunction22(((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> join(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22))).equals("12345678910111213141516171819202122")); + acceptFunction22Unit( ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); } + */ /* // The JFunctions in 2.12.0-M4 are not Serializable anymore @Test public void isSerializable() { - scala.runtime.java8.JFunction0 f0 = () -> "foo"; + scala.Function0 f0 = () -> "foo"; assertEquals("foo", SerializationUtils.clone(f0).apply()); - scala.runtime.java8.JFunction1 f1 = (a) -> a.toUpperCase(); + scala.Function1 f1 = (a) -> a.toUpperCase(); assertEquals("FOO", SerializationUtils.clone(f1).apply("foo")); - scala.runtime.java8.JFunction2 f2 = (a, b) -> a + b; + scala.Function2 f2 = (a, b) -> a + b; assertEquals("foobar", SerializationUtils.clone(f2).apply("foo", "bar")); - scala.runtime.java8.JFunction3 f3 = (a, b, c) -> a + b + c; + scala.Function3 f3 = (a, b, c) -> a + b + c; assertEquals("foobarbaz", SerializationUtils.clone(f3).apply("foo", "bar", "baz")); } */ + /* + // This version is for Scala 2.12.0-RC1 and is not compatible with 2.11. It's commented out to allow cross-building. private static scala.concurrent.Future futureExample( scala.concurrent.Future future, scala.concurrent.ExecutionContext ec) { - return future.map(func(s -> s.toUpperCase()), ec).map(func(s -> s.length()), ec); + return future.map(s -> s.toUpperCase(), ec).map(s -> s.length(), ec); } + */ private static void sideEffect() { } diff --git a/src/test/java/scala/runtime/java8/SpecializedFactoryTest.java b/src/test/java/scala/runtime/java8/SpecializedFactoryTest.java deleted file mode 100644 index bd4dddb..0000000 --- a/src/test/java/scala/runtime/java8/SpecializedFactoryTest.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ -package scala.runtime.java8; - -import org.junit.Test; -import scala.runtime.BoxedUnit; - -public class SpecializedFactoryTest { - @Test public void intIntFunction() { - scala.Function1 f1 = JFunction.funcSpecialized((int x) -> x); - assert(f1 instanceof JFunction1$mcII$sp); - - scala.Function1 f2 = JFunction.procSpecialized((int x) -> System.out.print("")); - assert(f2 instanceof JFunction1$mcVI$sp); - - scala.Function0 f3 = JFunction.procSpecialized(() -> System.out.print("")); - assert (f3 instanceof JFunction0$mcV$sp); - } -} From 1aecdb54c7a1eac544557115158fc9cb68b5bde3 Mon Sep 17 00:00:00 2001 From: Christian Schmitt Date: Sat, 13 Aug 2016 11:40:53 +0200 Subject: [PATCH 108/340] adds the scala.runtime.java8 package to the published jar --- build.sbt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9b06450..cecd83f 100644 --- a/build.sbt +++ b/build.sbt @@ -8,6 +8,13 @@ def jwrite(dir: java.io.File)(name: String, content: String) = { f } +def osgiExport(scalaVersion: String, version: String) = { + (CrossVersion.partialVersion(scalaVersion) match { + case Some((2, 11)) => Seq(s"scala.runtime.java8.*;version=${version}") + case _ => Nil + }) ++ Seq(s"scala.compat.java8.*;version=${version}") +} + lazy val commonSettings = Seq( scalaVersion := "2.11.8", crossScalaVersions := List("2.11.8", "2.12.0-M5"), @@ -36,7 +43,7 @@ lazy val root = (project in file(".")). settings( fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath - OsgiKeys.exportPackage := Seq(s"scala.compat.java8.*;version=${version.value}"), + OsgiKeys.exportPackage := osgiExport(scalaVersion.value, version.value), OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), From 90270f4b861e976715e07fb7da3561d401445191 Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Fri, 9 Sep 2016 16:50:59 +0200 Subject: [PATCH 109/340] Restore backwards compatibility in Scala 2.12.0-RC1 (#78) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - The various JFunction and JProcedure sources that were removed from Scala in https://github.com/scala/scala/pull/5298 are now included here when building for Scala 2.12.x (except M5). - Code that relies on specialized JFunction types being subtypes of the generic JFunction types will inevitably break. This is unavoidable. The specialized types are still part of Scala but they extend Scala function types directly. - All JFunctionN types and JFunction.func methods are deprecated. They are provided for source compatibility between 2.11 and 2.12 only. - The JProcedureN classes, JFunction.funcSpecialized methods and JFunction.proc methods are still useful in 2.12 for easy interoperability between Scala specialization and Java’s primitive types from Java code. - Generate JFunction and JProcedure sources: Just like for 2.11, we generate the sources again for 2.12 (after M5). I wrote a new code generator which is much simpler than the old one (because there is less and simpler code to generate). We can remove the old one when we drop support for Scala 2.11. - Move code back from scala.runtime.java8 to scala.compat.java8: The standard library contains some specialized JFunction* classes in scala.runtime.java8, so we cannot use the same package here if we ever want this to work with Java 9 modules. Therefore everything is moved back to scala.compat.java8 where it was in 0.7. We have to drop compatibility with Scala 2.12.0-M5 which contains these classes as part of scala-library in scala.runtime.java8. - Update to proper Scala 2.12.0-RC so we can build a release --- build.sbt | 25 +-- fnGen/WrapFnGen.scala | 4 +- project/CodeGen.scala | 103 +++++++++++- .../{runtime => compat}/java8/BoxingTest.java | 7 +- .../java/scala/compat/java8/LambdaTest.java | 147 ++++++++++++++++++ .../scala/compat/java8/SpecializedTest.scala | 2 +- .../java8/SpecializedTestSupport.java | 3 +- .../java/scala/runtime/java8/LambdaTest.java | 116 -------------- 8 files changed, 269 insertions(+), 138 deletions(-) rename src/test/java/scala/{runtime => compat}/java8/BoxingTest.java (75%) create mode 100644 src/test/java/scala/compat/java8/LambdaTest.java rename src/test/java/scala/{runtime => compat}/java8/SpecializedTestSupport.java (91%) delete mode 100644 src/test/java/scala/runtime/java8/LambdaTest.java diff --git a/build.sbt b/build.sbt index cecd83f..81e6d00 100644 --- a/build.sbt +++ b/build.sbt @@ -2,8 +2,8 @@ val disableDocs = sys.props("nodocs") == "true" lazy val JavaDoc = config("genjavadoc") extend Compile -def jwrite(dir: java.io.File)(name: String, content: String) = { - val f = dir / "scala" / "runtime" / "java8" / s"${name}.java" +def jwrite(dir: java.io.File, pck: String = "scala/compat/java8")(name: String, content: String) = { + val f = dir / pck / s"${name}.java" IO.write(f, content) f } @@ -16,8 +16,8 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - scalaVersion := "2.11.8", - crossScalaVersions := List("2.11.8", "2.12.0-M5"), + crossScalaVersions := List("2.12.0-RC1", "2.11.8"), + scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", version := "0.8.0-SNAPSHOT" ) @@ -69,15 +69,16 @@ lazy val root = (project in file(".")). }.taskValue, sourceGenerators in Compile <+= (sourceManaged in Compile, scalaVersion) map { (dir, v) => + val write = jwrite(dir) _ if(v.startsWith("2.11.")) { - val write = jwrite(dir) _ Seq(write("JFunction", CodeGen.factory)) ++ - (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ - (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ - CodeGen.specializedF0.map(write.tupled) ++ - CodeGen.specializedF1.map(write.tupled) ++ - CodeGen.specializedF2.map(write.tupled) - } else Seq.empty + (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ + (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ + CodeGen.specializedF0.map(write.tupled) ++ + CodeGen.specializedF1.map(write.tupled) ++ + CodeGen.specializedF2.map(write.tupled) ++ + CodeGen.packageDummy.map((jwrite(dir, "java/runtime/java8") _).tupled) + } else CodeGen.create212.map(write.tupled) }, sourceGenerators in Test <+= sourceManaged in Test map { dir => @@ -86,7 +87,7 @@ lazy val root = (project in file(".")). initialize := { // Run previously configured inialization... - initialize.value + val _ = initialize.value // ... and then check the Java version. val specVersion = sys.props("java.specification.version") if (Set("1.5", "1.6", "1.7") contains specVersion) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 02938f5..46779bc 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -1,12 +1,12 @@ /* - * Copyright (C) 2015 Typesafe Inc. + * Copyright (C) 2015-2016 Lightbend Inc. */ object WrapFnGen { val copyright = s""" |/* - | * Copyright (C) 2015, Typesafe Inc. + | * Copyright (C) 2015-2016, Lightbend Inc. | * This file auto-generated by WrapFnGen.scala. Do not modify directly. | */ |""".stripMargin diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 15c475f..250637a 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Typesafe Inc. + * Copyright (C) 2012-2016 Lightbend Inc. */ sealed abstract class Type(val code: Char, val prim: String, val ref: String) { @@ -25,7 +25,7 @@ object Type { } object CodeGen { - def packaging = "package scala.runtime.java8;" + def packaging = "package scala.compat.java8;" case class arity(n: Int) { val ns = (1 to n).toList @@ -288,7 +288,7 @@ object CodeGen { private val copyright = """ |/* - | * Copyright (C) 2012-2015 Typesafe Inc. + | * Copyright (C) 2012-2016 Lightbend Inc. | */""".stripMargin.trim private def function0SpecMethods = { @@ -433,4 +433,101 @@ object CodeGen { } def indent(s: String) = s.linesIterator.map(" " + _).mkString("\n") + + /** Create a dummy class to put into scala.runtime.java8 for Scala 2.11 so that wildcard imports from the + * package won't fail. This allows importing both `scala.runtime.java8.*` and `scala.compat.java8.*` for + * source compatibility between 2.11 and 2.12. + */ + def packageDummy: Seq[(String, String)] = Seq( + ( "PackageDummy", + s"""$copyright + | + |package scala.runtime.java8; + | + |public final class PackageDummy { + | private PackageDummy() {} + |} + """.stripMargin) + ) + + /** Create the simpler JFunction and JProcedure sources for Scala 2.12+ */ + def create212: Seq[(String, String)] = { + val blocks = for(i <- 0 to 22) yield { + val ts = (1 to i).map(i => s"T$i").mkString(", ") + val tsComma = if(ts.isEmpty) "" else s"$ts," + val tsAngled = if(ts.isEmpty) "" else s"<$ts>" + val paramTs = (1 to i).map(i => s"T$i t$i").mkString(", ") + val argTs = (1 to i).map(i => s"t$i").mkString(", ") + + ( + ( s"JFunction$i", + s"""$copyright + |$packaging + | + |/** @deprecated Use scala.Function$i in Scala 2.12 */ + |@Deprecated + |@FunctionalInterface + |public interface JFunction$i<$tsComma R> extends scala.Function$i<$tsComma R>, java.io.Serializable {} + """.stripMargin), + ( s"JProcedure$i", + s"""$copyright + |$packaging + | + |import scala.runtime.BoxedUnit; + | + |@FunctionalInterface + |public interface JProcedure$i$tsAngled extends scala.Function$i<$tsComma BoxedUnit> { + | void applyVoid($paramTs); + | default BoxedUnit apply($paramTs) { applyVoid($argTs); return BoxedUnit.UNIT; } + |} + """.stripMargin), + s""" /** @deprecated Not needed anymore in Scala 2.12 */ + | @Deprecated + | public static <$tsComma R> scala.Function$i<$tsComma R> func(scala.Function$i<$tsComma R> f) { return f; } + | public static $tsAngled scala.Function$i<$tsComma BoxedUnit> proc(JProcedure$i$tsAngled p) { return p; } + """.stripMargin + ) + } + + def specialize(args: String): List[(Int, String, String)] = { + def combinations(l: List[String]): List[List[Char]] = + l.foldRight(List(Nil: List[Char])) { (s, z) => s.toList.flatMap(c => z.map(c :: _)) } + val split = args.split(",") + combinations(split.toList).map { s => + val types = s.map { + case 'B' => "Byte" + case 'S' => "Short" + case 'V' => "BoxedUnit" + case 'I' => "Integer" + case 'J' => "Long" + case 'C' => "Character" + case 'F' => "Float" + case 'D' => "Double" + case 'Z' => "Boolean" + } + (split.length-1, (types.tail :+ types.head).mkString(", "), "$mc" + s.mkString + "$sp") + } + } + + val specialized = + List("V", "V,IJFD", "V,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => + s" public static scala.Function$i<$a> procSpecialized(JFunction$i$sp f) { return f; }" } ++ + List("BSIJCFDZ", "ZIFJD,IJFD", "ZIFJD,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => + s" public static scala.Function$i<$a> funcSpecialized(JFunction$i$sp f) { return f; }" } + + (blocks.map(_._1) ++ blocks.map(_._2)) :+ + ( "JFunction", + s"""$copyright + |$packaging + | + |import scala.runtime.BoxedUnit; + |import scala.runtime.java8.*; + | + |public final class JFunction { + | private JFunction() {} + |${specialized.mkString("\n")} + |${blocks.map(_._3).mkString("\n")} + |} + """.stripMargin) + } } diff --git a/src/test/java/scala/runtime/java8/BoxingTest.java b/src/test/java/scala/compat/java8/BoxingTest.java similarity index 75% rename from src/test/java/scala/runtime/java8/BoxingTest.java rename to src/test/java/scala/compat/java8/BoxingTest.java index 083b5de..94b05ff 100644 --- a/src/test/java/scala/runtime/java8/BoxingTest.java +++ b/src/test/java/scala/compat/java8/BoxingTest.java @@ -1,14 +1,15 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.runtime.java8; +package scala.compat.java8; import org.junit.Test; +import scala.runtime.java8.*; public class BoxingTest { @Test public void nullBoxesInterpretedAsZeroF1() { - JFunction1$mcII$sp jFunction1 = new JFunction1$mcII$sp() { + scala.Function1 jFunction1 = new JFunction1$mcII$sp() { @Override public int apply$mcII$sp(int v1) { return v1 + 1; @@ -20,7 +21,7 @@ public void nullBoxesInterpretedAsZeroF1() { @Test public void nullBoxesInterpretedAsZeroF2() { - JFunction2$mcIII$sp jFunction2 = new JFunction2$mcIII$sp() { + scala.Function2 jFunction2 = new JFunction2$mcIII$sp() { @Override public int apply$mcIII$sp(int v1, int v2) { return v1 + v2 + 1; diff --git a/src/test/java/scala/compat/java8/LambdaTest.java b/src/test/java/scala/compat/java8/LambdaTest.java new file mode 100644 index 0000000..36634c4 --- /dev/null +++ b/src/test/java/scala/compat/java8/LambdaTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2012-2015 Typesafe Inc. + */ +package scala.compat.java8; + +import org.apache.commons.lang3.SerializationUtils; +import scala.runtime.*; + +import static junit.framework.Assert.assertEquals; +import static scala.compat.java8.JFunction.*; +import static scala.compat.java8.TestAPI.*; + +import org.junit.Test; + + +public class LambdaTest { + @Test + public void lambdaDemo() { + // Scala 2.12+ only: + //scala.Function1 f1 = (String s) -> s; + + // Not allowed with Scala 2.10 nor 2.11 + // "incompatible types: Function1 is not a functional interface" + // scala.Function1 f = (String s) -> s; + + // Function1 is not a functional interface because it has abstract + // methods in addition to apply, namely `compose` and `andThen` + // (which are implemented in Scala-derived subclasses with mixin + // inheritance), and the specialized variants of apply (also provided + // by scalac.) + + // That's a pity, but we can get pretty close with this library! + + // We have to tell javac to use `JFunction1` as the functional interface. + // Scala 2.12 does not have or need JFunction anymore. We provide it as a + // deprecated stub for backwards compatibility. Use `scala.Function1` for + // code that targets Scala 2.12+ exclusively. + JFunction1 f1 = (String s) -> s; + + // That's more or less equivalent to the old, anonymous class syntax: + new JFunction1() { + public String apply(String s) { return s; } + }; + + // You might have seen this form before: + new AbstractFunction1() { + public String apply(String s) { return s; } + }; + + // However, we can't use `AbstractFunction1` as a functional interface + // as it is a class. Further + + // F1 is a subclass of Function1: + scala.Function1 f2 = f1; + + // Factory methods in `JFunction` can reduce the verbosity a little: + // `func` is actually just an identity method; it only exists to + // trigger lambda creation using the `JFunction1` functional interface. + scala.Function1 f3 = func((String s) -> s); + + // Note that javac's type inference can infer the parameter type here, + // based on the acribed type of `f4`. + scala.Function1 f4 = func(s -> s); + + // f1.apply(""); + + // Specialized variants of the `apply` method are provided but implementing a specialized + // Scala function in this straight-forward way results in boxing and unboxing because the + // Java lambda operates on boxed types: + JFunction1 f5 = (i) -> -i; + assert(f5.apply(1) == -1); + assert(f5.apply$mcII$sp(1) == -1); + + // We provide `JFunction.funcSpecialized` and `JFunction.procSpecialized` methods to avoid + // boxing: + scala.Function1 f5b = funcSpecialized((int i) -> -i); + assert(f5b.apply(1) == -1); + assert(f5b.apply$mcII$sp(1) == -1); + + // as are `curried`, `tupled`, `compose`, `andThen`. + f3.compose(f3).andThen(f3).apply(""); + scala.Function2 f6 = func((s1, s2) -> join(s1, s2)); + assert(f6.curried().apply("1").apply("2").equals("12")); + + // Functions returning unit can use the `JProcedure1`, ... functional interfaces + // in order to convert a void lamdba return to Scala's Unit: + JProcedure1 f7b = s -> sideEffect(); + scala.Function1 f7c = f7b; + + // The easiest way to do this is via `JFunction.proc`, .... + // + // Note that the lambda has a return type of `void` if the last + // statement is a call to a `void` returning method, or if it is + // a `return`. + scala.Function1 f7 = proc(s -> sideEffect()); + scala.Function1 f8 = proc(s -> {s.toUpperCase(); return;}); + + // Function0 is also available + scala.Function0 f9 = func(() -> "42"); + assert(f9.apply().equals("42")); + + // You can go up to 22 (the highest arity function defined in the Scala standard library.) + assert(acceptFunction1(func(v1 -> v1.toUpperCase())).equals("1")); + acceptFunction1Unit(proc(v1 -> sideEffect())); + acceptFunction1Unit(proc(v1 -> {v1.toUpperCase(); return;})); + + assert(acceptFunction2(func((v1, v2) -> join(v1, v2))).equals("12")); + acceptFunction2Unit(proc((v1, v2) -> {v1.toUpperCase(); return;})); + + assert(acceptFunction3(func((v1, v2, v3) -> join(v1, v2, v3))).equals("123")); + acceptFunction3Unit(proc((v1, v2, v3) -> {v1.toUpperCase(); return;})); + + assert(acceptFunction22(func((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> join(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22))).equals("12345678910111213141516171819202122")); + acceptFunction22Unit( proc((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return;})); + } + + @Test + public void isSerializable() { + JFunction0 f0 = () -> "foo"; + assertEquals("foo", SerializationUtils.clone(f0).apply()); + + JFunction1 f1 = (a) -> a.toUpperCase(); + assertEquals("FOO", SerializationUtils.clone(f1).apply("foo")); + + JFunction2 f2 = (a, b) -> a + b; + assertEquals("foobar", SerializationUtils.clone(f2).apply("foo", "bar")); + + JFunction3 f3 = (a, b, c) -> a + b + c; + assertEquals("foobarbaz", SerializationUtils.clone(f3).apply("foo", "bar", "baz")); + } + + private static scala.concurrent.Future futureExample( + scala.concurrent.Future future, scala.concurrent.ExecutionContext ec) { + return future.map(func(s -> s.toUpperCase()), ec).map(func(s -> s.length()), ec); + } + + private static void sideEffect() { + } + + private static String join(String... ss) { + String result = ""; + for (String s : ss) { + result = result + s; + } + return result; + } +} diff --git a/src/test/java/scala/compat/java8/SpecializedTest.scala b/src/test/java/scala/compat/java8/SpecializedTest.scala index 707ad82..e6b3239 100644 --- a/src/test/java/scala/compat/java8/SpecializedTest.scala +++ b/src/test/java/scala/compat/java8/SpecializedTest.scala @@ -4,7 +4,7 @@ package scala.compat.java8 import org.junit.Test -import scala.runtime.java8.SpecializedTestSupport.IntIdentity +import SpecializedTestSupport.IntIdentity class SpecializedTest { @Test def specializationWorks() { diff --git a/src/test/java/scala/runtime/java8/SpecializedTestSupport.java b/src/test/java/scala/compat/java8/SpecializedTestSupport.java similarity index 91% rename from src/test/java/scala/runtime/java8/SpecializedTestSupport.java rename to src/test/java/scala/compat/java8/SpecializedTestSupport.java index 2ba2833..c7e4386 100644 --- a/src/test/java/scala/runtime/java8/SpecializedTestSupport.java +++ b/src/test/java/scala/compat/java8/SpecializedTestSupport.java @@ -1,11 +1,12 @@ /* * Copyright (C) 2012-2015 Typesafe Inc. */ -package scala.runtime.java8; +package scala.compat.java8; import java.util.Arrays; import java.util.List; import org.junit.Assert; +import scala.runtime.java8.*; public class SpecializedTestSupport { public static class IntIdentity implements JFunction1$mcII$sp { diff --git a/src/test/java/scala/runtime/java8/LambdaTest.java b/src/test/java/scala/runtime/java8/LambdaTest.java deleted file mode 100644 index 9d67926..0000000 --- a/src/test/java/scala/runtime/java8/LambdaTest.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2012-2015 Typesafe Inc. - */ -package scala.runtime.java8; - -import org.apache.commons.lang3.SerializationUtils; -import scala.runtime.*; - -import static junit.framework.Assert.assertEquals; -import static scala.runtime.java8.TestAPI.*; - -import org.junit.Test; - - -public class LambdaTest { - /* - // This version is for Scala 2.12.0-RC1 and is not compatible with 2.11. It's commented out to allow cross-building. - @Test - public void lambdaDemo() { - scala.Function1 f1 = (String s) -> s; - - // That's more or less equivalent to the old, anonymous class syntax: - new scala.Function1() { - public String apply(String s) { return s; } - }; - - // You might have seen this form before: - new AbstractFunction1() { - public String apply(String s) { return s; } - }; - - // However, we can't use `AbstractFunction1` as a functional interface - // as it is a class. Further - - // F1 is a subclass of Function1: - scala.Function1 f2 = f1; - - scala.Function1 f3 = (String s) -> s; - scala.Function1 f4 = s -> s; - - // Specialized variants of the `apply` method are implenented in the - // functional interface - scala.Function1 f5 = (i -> -i); - assert(f5.apply(1) == -1); - assert(f5.apply$mcII$sp(1) == -1); - - // as are `curried`, `tupled`, `compose`, `andThen`. - f3.compose(f3).andThen(f3).apply(""); - scala.Function2 f6 = ((s1, s2) -> join(s1, s2)); - assert(f6.curried().apply("1").apply("2").equals("12")); - - // Functions returning unit must return BoxedUnit.UNIT explicitly. - // - // Note that the lambda has a return type of `void` if the last - // statement is a call to a `void` returning method, or if it is - // a `return`. - scala.Function1 f7 = (s -> { sideEffect(); return scala.runtime.BoxedUnit.UNIT; }); - scala.Function1 f8 = (s -> { s.toUpperCase(); return scala.runtime.BoxedUnit.UNIT; }); - - // Function0 is also available - scala.Function0 f9 = (() -> "42"); - assert(f9.apply().equals("42")); - - // You can go up to 22 (the highest arity function defined in the Scala standard library.) - assert(acceptFunction1((v1 -> v1.toUpperCase())).equals("1")); - acceptFunction1Unit((v1 -> {sideEffect(); return scala.runtime.BoxedUnit.UNIT;})); - acceptFunction1Unit((v1 -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - - assert(acceptFunction2(((v1, v2) -> join(v1, v2))).equals("12")); - acceptFunction2Unit(((v1, v2) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - - assert(acceptFunction3(((v1, v2, v3) -> join(v1, v2, v3))).equals("123")); - acceptFunction3Unit(((v1, v2, v3) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - - assert(acceptFunction22(((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> join(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22))).equals("12345678910111213141516171819202122")); - acceptFunction22Unit( ((v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -> {v1.toUpperCase(); return scala.runtime.BoxedUnit.UNIT;})); - } - */ - - /* - // The JFunctions in 2.12.0-M4 are not Serializable anymore - @Test - public void isSerializable() { - scala.Function0 f0 = () -> "foo"; - assertEquals("foo", SerializationUtils.clone(f0).apply()); - - scala.Function1 f1 = (a) -> a.toUpperCase(); - assertEquals("FOO", SerializationUtils.clone(f1).apply("foo")); - - scala.Function2 f2 = (a, b) -> a + b; - assertEquals("foobar", SerializationUtils.clone(f2).apply("foo", "bar")); - - scala.Function3 f3 = (a, b, c) -> a + b + c; - assertEquals("foobarbaz", SerializationUtils.clone(f3).apply("foo", "bar", "baz")); - } - */ - - /* - // This version is for Scala 2.12.0-RC1 and is not compatible with 2.11. It's commented out to allow cross-building. - private static scala.concurrent.Future futureExample( - scala.concurrent.Future future, scala.concurrent.ExecutionContext ec) { - return future.map(s -> s.toUpperCase(), ec).map(s -> s.length(), ec); - } - */ - - private static void sideEffect() { - } - - private static String join(String... ss) { - String result = ""; - for (String s : ss) { - result = result + s; - } - return result; - } -} From d3b97e65c3f009ec1c0e433c2fc55d375b20d3dd Mon Sep 17 00:00:00 2001 From: Stefan Zeiger Date: Fri, 9 Sep 2016 17:03:48 +0200 Subject: [PATCH 110/340] Build on 2.12.0-M5 and 2.12.0-RC1, both on Travis and in sbt --- .travis.yml | 1 + build.sbt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4eeb932..8d11810 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ script: scala: - 2.11.8 - 2.12.0-M5 + - 2.12.0-RC1 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index 81e6d00..66e0a7f 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := List("2.12.0-RC1", "2.11.8"), + crossScalaVersions := List("2.12.0-RC1", "2.12.0-M5", "2.11.8"), scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", version := "0.8.0-SNAPSHOT" From eabbd5fb4ea5fe6d3043e5e43896a60ccc509ba1 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 19 Oct 2016 08:13:03 +1100 Subject: [PATCH 111/340] Bump to Scala 2.12.0-RC2 Temporarily uses genjavadoc for 2.12.0-RC1, I've requested a new version over in https://github.com/typesafehub/genjavadoc/pull/90 --- .travis.yml | 2 +- build.sbt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8d11810..1cad8a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ script: scala: - 2.11.8 - 2.12.0-M5 - - 2.12.0-RC1 + - 2.12.0-RC2 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index 66e0a7f..ad58329 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := List("2.12.0-RC1", "2.12.0-M5", "2.11.8"), + crossScalaVersions := List("2.12.0-RC2", "2.12.0-M5", "2.11.8"), scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", version := "0.8.0-SNAPSHOT" @@ -110,7 +110,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.fullMapped { case "2.12.0-RC2" => "2.12.0-RC1" case x => x}), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From f4f54a3251608f890f0d5c5f739cf0248176b1ec Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 30 Oct 2016 08:59:17 +1100 Subject: [PATCH 112/340] Bump to Scala 2.12.0 --- .travis.yml | 3 +-- build.sbt | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1cad8a5..1c947dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,7 @@ script: - admin/build.sh scala: - 2.11.8 - - 2.12.0-M5 - - 2.12.0-RC2 + - 2.12.0 jdk: - oraclejdk8 notifications: diff --git a/build.sbt b/build.sbt index ad58329..05834ad 100644 --- a/build.sbt +++ b/build.sbt @@ -16,7 +16,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := List("2.12.0-RC2", "2.12.0-M5", "2.11.8"), + crossScalaVersions := List("2.12.0", "2.11.8"), scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", version := "0.8.0-SNAPSHOT" @@ -110,7 +110,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.fullMapped { case "2.12.0-RC2" => "2.12.0-RC1" case x => x}), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.fullMapped { case "2.12.0" => "2.12.0-RC1" case x => x}), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From 7e5c81f0eb7b19939a0d6332d78641ba23be5a32 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Sun, 30 Oct 2016 09:09:27 +1100 Subject: [PATCH 113/340] Bump to new snapshot version --- benchmark/build.sbt | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/build.sbt b/benchmark/build.sbt index 8aa4d2b..79900aa 100644 --- a/benchmark/build.sbt +++ b/benchmark/build.sbt @@ -9,7 +9,7 @@ lazy val root = (project in file(".")).settings( crossScalaVersions := List("2.11.8" /* TODO, "2.12.0-M4"*/), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", - unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.8.0-SNAPSHOT.jar"), + unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.9.0-SNAPSHOT.jar"), // This would be nicer but sbt-jmh doesn't like it: //unmanagedClasspath in Compile += Attributed.blank(baseDirectory.value / "../target/scala-2.11/classes"), generateJmh := (runMain in Compile).toTask(" bench.codegen.GenJmhBench").value, diff --git a/build.sbt b/build.sbt index ad58329..40a9ae4 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ lazy val commonSettings = Seq( crossScalaVersions := List("2.12.0-RC2", "2.12.0-M5", "2.11.8"), scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", - version := "0.8.0-SNAPSHOT" + version := "0.9.0-SNAPSHOT" ) lazy val fnGen = (project in file("fnGen")). From 2030bfab679932355964b92e49324c6b384bc6d0 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Wed, 4 Jan 2017 11:18:06 -0800 Subject: [PATCH 114/340] Include 2.12 maven badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e6caf3f..1e8a300 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) +## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12*) A Java 8 compatibility kit for Scala. From 94e8a88c8e9e9af308ce011916dae56626b02935 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 25 Apr 2017 22:08:54 +0200 Subject: [PATCH 115/340] Upate scala-module-plugin, updates to tag-based publishing After this patch, `.travis.yml` no longer defines any Scala versions, this is always done in sbt. This way there's a single place to update Scala versions. --- .travis.yml | 4 --- admin/README.md | 70 +++++++++++++++++++++++----------------- admin/build.sh | 46 ++++++++++++++++++++------ build.sbt | 12 +++---- project/build.properties | 2 +- project/plugins.sbt | 2 +- 6 files changed, 86 insertions(+), 50 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c947dc..0122f29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: scala sudo: false env: global: - - PUBLISH_JDK=oraclejdk8 # PGP_PASSPHRASE - secure: "BzgzRZLYa52rS/hBfzf43b++CfDhdcd3Mmu8tsyBHgThSQOd2YBLbV5kWD8aYVFKVHfW7XX0PTe3F+rR/fFZqGItE6o8Px0Y7Vzb5pqjlaQdxFEJ+WrsnshS0xuAKZ7OwVHRp+d+jznaCwRxEo2vpW3ko1OPAJ8cxfhVL/4C1I0=" # SONA_USER @@ -11,9 +10,6 @@ env: - secure: "FZC+FZnBNeklA150vW5QDZJ5J7t+DExJrgyXWM46Wh0MobjH8cvydgC3qatItb0rDBV8l7zO1LDwl2KEi92aefw2a8E49z6qVOHgUXiI3SAx7M0UO0FFeKPmTXCLcBlbnGLcUqNjIZfuIEufQvPblKTl8qN4eMmcMn9jsNzJr28=" script: - admin/build.sh -scala: - - 2.11.8 - - 2.12.0 jdk: - oraclejdk8 notifications: diff --git a/admin/README.md b/admin/README.md index 3b38f19..46626b4 100644 --- a/admin/README.md +++ b/admin/README.md @@ -12,49 +12,61 @@ To configure tag driven releases from Travis CI. 1. Generate a key pair for this repository with `./admin/genKeyPair.sh`. Edit `.travis.yml` and `admin/build.sh` as prompted. - 2. Publish the public key to https://pgp.mit.edu - 3. Store other secrets as encrypted environment variables with `admin/encryptEnvVars.sh`. + 1. Publish the public key to https://pgp.mit.edu + 1. Store other secrets as encrypted environment variables with `admin/encryptEnvVars.sh`. Edit `.travis.yml` as prompted. - 4. Edit `.travis.yml` to use `./admin/build.sh` as the build script, + 1. Edit `.travis.yml` to use `./admin/build.sh` as the build script, and edit that script to use the tasks required for this project. - 5. Edit `.travis.yml` to select which JDK will be used for publishing. + 1. Edit `build.sbt`'s `scalaVersionsByJvm in ThisBuild` to select Scala and JVM version + combinations that will be used for publishing. -It is important to add comments in .travis.yml to identify the name +It is important to add comments in `.travis.yml` to identify the name of each environment variable encoded in a `:secure` section. -After all of these steps, your .travis.yml should contain config of the -form: - - language: scala - env: - global: - - PUBLISH_JDK=openjdk6 - # PGP_PASSPHRASE - - secure: "XXXXXX" - # SONA_USER - - secure: "XXXXXX" - # SONA_PASS - - secure: "XXXXXX" - script: - - admin/build.sh +After these steps, your `.travis.yml` should contain config of the form: + +``` +language: scala + +env: + global: + # PGP_PASSPHRASE + - secure: "XXXXXX" + # SONA_USER + - secure: "XXXXXX" + # SONA_PASS + - secure: "XXXXXX" + +script: admin/build.sh + +jdk: + - openjdk6 + - oraclejdk8 + +notifications: + email: + - a@b.com +``` If Sonatype credentials change in the future, step 3 can be repeated without generating a new key. -Be sure to use SBT 0.13.7 or higher to avoid [#1430](https://github.com/sbt/sbt/issues/1430)! - ### Testing - 1. Follow the release process below to create a dummy release (e.g. 0.1.0-TEST1). + 1. Follow the release process below to create a dummy release (e.g., `v0.1.0-TEST1`). Confirm that the release was staged to Sonatype but do not release it to Maven central. Instead, drop the staging repository. ### Performing a release - 1. Create a GitHub "Release" (with a corresponding tag) via the GitHub + 1. Create a GitHub "Release" with a corresponding tag (e.g., `v0.1.1`) via the GitHub web interface. - 2. Travis CI will schedule a build for this release. Review the build logs. - 3. Log into https://oss.sonatype.org/ and identify the staging repository. - 4. Sanity check its contents - 5. Release staging repository to Maven and send out release announcement. - + 1. The release will be published using the Scala and JVM version combinations specified + in `scalaVersionsByJvm` in `build.sbt`. + - If you need to release against a different Scala version, include the Scala version + and the JVM version to use in the tag name, separated by `#`s (e.g., `v0.1.1#2.13.0-M1#8`). + Note that the JVM version needs to be listed in `.travis.yml` for the build to run. + 1. Travis CI will schedule a build for this release. Review the build logs. + 1. Log into https://oss.sonatype.org/ and identify the staging repository. + 1. Sanity check its contents. + 1. Release staging repository to Maven and send out release announcement. diff --git a/admin/build.sh b/admin/build.sh index b67abcf..7d27ba0 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -2,16 +2,44 @@ set -e -# prep environment for publish to sonatype staging if the HEAD commit is tagged +# Builds of tagged revisions are published to sonatype staging. -# git on travis does not fetch tags, but we have TRAVIS_TAG -# headTag=$(git describe --exact-match ||:) +# Travis runs a build on new revisions and on new tags, so a tagged revision is built twice. +# Builds for a tag have TRAVIS_TAG defined, which we use for identifying tagged builds. +# Checking the local git clone would not work because git on travis does not fetch tags. -if [ "$TRAVIS_JDK_VERSION" == "$PUBLISH_JDK" ] && [[ "$TRAVIS_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)? ]]; then - echo "Going to release from tag $TRAVIS_TAG!" - myVer=$(echo $TRAVIS_TAG | sed -e s/^v// | sed -e 's/_[0-9]*\.[0-9]*//') - publishVersion='set every version := "'$myVer'"' - extraTarget="publish-signed" +# The version number to be published is extracted from the tag, e.g., v1.2.3 publishes +# version 1.2.3 using all Scala versions in build.sbt's `crossScalaVersions`. + +# When a new, binary incompatible Scala version becomes available, a previously released version +# can be released using that new Scala version by creating a new tag containing the Scala and the +# JVM version after hashes, e.g., v1.2.3#2.13.0-M1#8. The JVM version needs to be listed in +# `.travis.yml`, otherwise the required build doesn't run. + +verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" +tagPat="^v$verPat(#$verPat#[0-9]+)?$" + +if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then + currentJvmVer=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | sed 's/^1\.//' | sed 's/[^0-9].*//') + + tagVer=$(echo $TRAVIS_TAG | sed s/#.*// | sed s/^v//) + publishVersion='set every version := "'$tagVer'"' + + scalaAndJvmVer=$(echo $TRAVIS_TAG | sed s/[^#]*// | sed s/^#//) + if [ "$scalaAndJvmVer" != "" ]; then + scalaVer=$(echo $scalaAndJvmVer | sed s/#.*//) + jvmVer=$(echo $scalaAndJvmVer | sed s/[^#]*// | sed s/^#//) + if [ "$jvmVer" != "$currentJvmVer" ]; then + echo "Not publishing $TRAVIS_TAG on Java version $currentJvmVer." + exit 0 + fi + publishScalaVersion='set every ScalaModulePlugin.scalaVersionsByJvm := Map('$jvmVer' -> List("'$scalaVer'" -> true))' + echo "Releasing $tagVer using Scala $scalaVer on Java version $jvmVer." + else + echo "Releasing $tagVer on Java version $currentJvmVer according to 'scalaVersionsByJvm' in build.sbt." + fi + + extraTarget="+publish-signed" cat admin/gpg.sbt >> project/plugins.sbt cp admin/publish-settings.sbt . @@ -22,4 +50,4 @@ if [ "$TRAVIS_JDK_VERSION" == "$PUBLISH_JDK" ] && [[ "$TRAVIS_TAG" =~ ^v[0-9]+\. openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d fi -sbt ++$TRAVIS_SCALA_VERSION "$publishVersion" clean update test publishLocal $extraTarget +sbt "$publishVersion" "$publishScalaVersion" clean update +test +publishLocal $extraTarget diff --git a/build.sbt b/build.sbt index 725a68c..bdb48fc 100644 --- a/build.sbt +++ b/build.sbt @@ -1,3 +1,9 @@ +import ScalaModulePlugin._ + +scalaVersionsByJvm in ThisBuild := Map( + 8 -> List("2.12.0", "2.11.8").map(_ -> true) +) + val disableDocs = sys.props("nodocs") == "true" lazy val JavaDoc = config("genjavadoc") extend Compile @@ -16,8 +22,6 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := List("2.12.0", "2.11.8"), - scalaVersion := crossScalaVersions.value.head, organization := "org.scala-lang.modules", version := "0.9.0-SNAPSHOT" ) @@ -36,10 +40,6 @@ lazy val root = (project in file(".")). settings( name := "scala-java8-compat" ). - settings( - // important!! must come here (why?) - scalaModuleOsgiSettings: _* - ). settings( fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath diff --git a/project/build.properties b/project/build.properties index 748703f..64317fd 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.7 +sbt.version=0.13.15 diff --git a/project/plugins.sbt b/project/plugins.sbt index 25f3373..293445d 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.3") +addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.8") From 2131f97af508242d3571f409570a929627556ab1 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 25 Apr 2017 22:13:59 +0200 Subject: [PATCH 116/340] Cross-build against 2.13.0-M1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index bdb48fc..42b2e56 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.0", "2.11.8").map(_ -> true) + 8 -> List("2.12.0", "2.11.8", "2.13.0-M1").map(_ -> true) ) val disableDocs = sys.props("nodocs") == "true" From 2002999f7b89f0e6d68e2d402f5b1d477642864a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 11 May 2017 11:52:35 -0700 Subject: [PATCH 117/340] fix busted Maven badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e8a300..87543d8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11*) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12*) +## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) A Java 8 compatibility kit for Scala. From bf6566f6080091b996ecbdf0f2e2580081edf57b Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 13:53:46 -0700 Subject: [PATCH 118/340] update company name, copyright year --- .travis.yml | 2 +- LICENSE | 4 ++-- .../compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java | 2 +- .../compat/java8/wrappers/IteratorPrimitiveIntWrapper.java | 2 +- .../compat/java8/wrappers/IteratorPrimitiveLongWrapper.java | 2 +- src/main/scala/scala/compat/java8/FutureConverters.scala | 2 +- src/main/scala/scala/compat/java8/OptionConverters.scala | 2 +- .../scala/compat/java8/PrimitiveIteratorConversions.scala | 2 +- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 2 +- src/test/java/scala/compat/java8/BoxingTest.java | 2 +- src/test/java/scala/compat/java8/FutureConvertersTest.java | 2 +- src/test/java/scala/compat/java8/LambdaTest.java | 2 +- src/test/java/scala/compat/java8/OptionConvertersTest.scala | 2 +- src/test/java/scala/compat/java8/SpecializedTest.scala | 2 +- src/test/java/scala/compat/java8/SpecializedTestSupport.java | 2 +- .../java/scala/compat/java8/StreamConvertersExampleTest.java | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0122f29..1baf295 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ jdk: - oraclejdk8 notifications: email: - - jason.zaugg@typesafe.com + - jason.zaugg@lightbend.com diff --git a/LICENSE b/LICENSE index ce51bda..6fdcc0c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2002-2013 EPFL -Copyright (c) 2011-2013 Typesafe, Inc. +Copyright (c) 2002-2017 EPFL +Copyright (c) 2011-2017 Lightbend, Inc. All rights reserved. diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java index 7c27293..f863b8c 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8.wrappers; diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java index 330a41c..10c5cf0 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8.wrappers; diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java index 9adff5f..2cf799d 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8.wrappers; diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index c065e49..7dc047a 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/main/scala/scala/compat/java8/OptionConverters.scala b/src/main/scala/scala/compat/java8/OptionConverters.scala index b99529a..f89dd22 100644 --- a/src/main/scala/scala/compat/java8/OptionConverters.scala +++ b/src/main/scala/scala/compat/java8/OptionConverters.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index da991c2..617f9e5 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index edc8723..0c5bf49 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.concurrent.java8 diff --git a/src/test/java/scala/compat/java8/BoxingTest.java b/src/test/java/scala/compat/java8/BoxingTest.java index 94b05ff..c093631 100644 --- a/src/test/java/scala/compat/java8/BoxingTest.java +++ b/src/test/java/scala/compat/java8/BoxingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8; diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index a87a6b8..8022499 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8; diff --git a/src/test/java/scala/compat/java8/LambdaTest.java b/src/test/java/scala/compat/java8/LambdaTest.java index 36634c4..7992f03 100644 --- a/src/test/java/scala/compat/java8/LambdaTest.java +++ b/src/test/java/scala/compat/java8/LambdaTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8; diff --git a/src/test/java/scala/compat/java8/OptionConvertersTest.scala b/src/test/java/scala/compat/java8/OptionConvertersTest.scala index 0b857c3..4c21bb5 100644 --- a/src/test/java/scala/compat/java8/OptionConvertersTest.scala +++ b/src/test/java/scala/compat/java8/OptionConvertersTest.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/test/java/scala/compat/java8/SpecializedTest.scala b/src/test/java/scala/compat/java8/SpecializedTest.scala index e6b3239..cc7f2f4 100644 --- a/src/test/java/scala/compat/java8/SpecializedTest.scala +++ b/src/test/java/scala/compat/java8/SpecializedTest.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/test/java/scala/compat/java8/SpecializedTestSupport.java b/src/test/java/scala/compat/java8/SpecializedTestSupport.java index c7e4386..274926f 100644 --- a/src/test/java/scala/compat/java8/SpecializedTestSupport.java +++ b/src/test/java/scala/compat/java8/SpecializedTestSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Typesafe Inc. + * Copyright (C) 2012-2015 Lightbend Inc. */ package scala.compat.java8; diff --git a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java index da16655..33b1800 100644 --- a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java +++ b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Typesafe Inc. + * Copyright (C) 2016 Lightbend Inc. */ import org.junit.Test; From 4675cd51873270ca181ae5d85bbcbded755bbe06 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 13:59:50 -0700 Subject: [PATCH 119/340] remove no-longer-needed workaround in build fixes #83 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 42b2e56..860a22a 100644 --- a/build.sbt +++ b/build.sbt @@ -110,7 +110,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.fullMapped { case "2.12.0" => "2.12.0-RC1" case x => x}), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From 27889a5e578b6b99571352e2add0498879f51916 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 13:54:33 -0700 Subject: [PATCH 120/340] eliminate warnings in build definition --- build.sbt | 21 ++++++++++++--------- project/plugins.sbt | 2 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/build.sbt b/build.sbt index 860a22a..2107029 100644 --- a/build.sbt +++ b/build.sbt @@ -68,9 +68,10 @@ lazy val root = (project in file(".")). (out ** "*.scala").get }.taskValue, - sourceGenerators in Compile <+= (sourceManaged in Compile, scalaVersion) map { (dir, v) => + sourceGenerators in Compile += Def.task { + val dir = (sourceManaged in Compile).value val write = jwrite(dir) _ - if(v.startsWith("2.11.")) { + if(scalaVersion.value.startsWith("2.11.")) { Seq(write("JFunction", CodeGen.factory)) ++ (0 to 22).map(n => write("JFunction" + n, CodeGen.fN(n))) ++ (0 to 22).map(n => write("JProcedure" + n, CodeGen.pN(n))) ++ @@ -79,11 +80,11 @@ lazy val root = (project in file(".")). CodeGen.specializedF2.map(write.tupled) ++ CodeGen.packageDummy.map((jwrite(dir, "java/runtime/java8") _).tupled) } else CodeGen.create212.map(write.tupled) - }, + }.taskValue, - sourceGenerators in Test <+= sourceManaged in Test map { dir => - Seq(jwrite(dir)("TestApi", CodeGen.testApi)) - }, + sourceGenerators in Test += Def.task { + Seq(jwrite((sourceManaged in Test).value)("TestApi", CodeGen.testApi)) + }.taskValue, initialize := { // Run previously configured inialization... @@ -103,9 +104,11 @@ lazy val root = (project in file(".")). ). settings( (inConfig(JavaDoc)(Defaults.configSettings) ++ (if (disableDocs) Nil else Seq( - packageDoc in Compile <<= packageDoc in JavaDoc, - sources in JavaDoc <<= (target, compile in Compile, sources in Compile) map {(t, c, s) => - val allJavaSources = (t / "java" ** "*.java").get ++ s.filter(_.getName.endsWith(".java")) + packageDoc in Compile := (packageDoc in JavaDoc).value, + sources in JavaDoc := { + val allJavaSources = + (target.value / "java" ** "*.java").get ++ + (sources in Compile).value.filter(_.getName.endsWith(".java")) allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc }, javacOptions in JavaDoc := Seq(), diff --git a/project/plugins.sbt b/project/plugins.sbt index 293445d..36ce0ab 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1,3 @@ +scalacOptions += "-Xfatal-warnings" + addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.8") From 7895a037da6200b9b3b77cfce77915c291066c41 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 14:12:55 -0700 Subject: [PATCH 121/340] remove a test involving a deprecated class --- src/test/scala/scala/compat/java8/StepConvertersTest.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index d061913..0add1f9 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -588,7 +588,6 @@ class StepConvertersTest { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) - _eh_( ci.PagedSeq.fromLines(Array("salmon").iterator).stepper ) good( ("salmon": ci.StringOps).stepper ) good( ("salmon": ci.WrappedString).stepper ) } From 1b5724ef6b54256d4687bb224aa1067c823168d5 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 13:57:27 -0700 Subject: [PATCH 122/340] remove unused code, fix warnings --- build.sbt | 3 +- fnGen/WrapFnGen.scala | 8 +- .../scala/compat/java8/FutureConverters.scala | 9 +- .../scala/compat/java8/OptionConverters.scala | 1 - .../java8/PrimitiveIteratorConversions.scala | 1 - .../scala/compat/java8/StreamConverters.scala | 2 +- .../java8/collectionImpl/Accumulator.scala | 6 +- .../collectionImpl/DoubleAccumulator.scala | 6 +- .../java8/collectionImpl/IntAccumulator.scala | 6 +- .../collectionImpl/LongAccumulator.scala | 6 +- .../compat/java8/collectionImpl/Stepper.scala | 4 +- .../java8/converterImpl/Accumulates.scala | 3 - .../java8/converterImpl/MakesSteppers.scala | 3 - .../java8/converterImpl/StepConverters.scala | 5 -- .../java8/converterImpl/StepsArray.scala | 2 - .../java8/converterImpl/StepsBitSet.scala | 2 - .../converterImpl/StepsFlatHashTable.scala | 1 - .../java8/converterImpl/StepsHashTable.scala | 1 - .../java8/converterImpl/StepsImmHashMap.scala | 2 - .../java8/converterImpl/StepsImmHashSet.scala | 4 - .../java8/converterImpl/StepsIndexedSeq.scala | 2 - .../java8/converterImpl/StepsIterable.scala | 4 - .../java8/converterImpl/StepsIterator.scala | 4 - .../java8/converterImpl/StepsLikeGapped.scala | 2 - .../converterImpl/StepsLikeImmHashMap.scala | 2 - .../converterImpl/StepsLikeIndexed.scala | 2 - .../converterImpl/StepsLikeIterator.scala | 2 - .../java8/converterImpl/StepsLikeSliced.scala | 2 - .../converterImpl/StepsLikeTrieIterator.scala | 2 - .../java8/converterImpl/StepsLinearSeq.scala | 2 - .../compat/java8/converterImpl/StepsMap.scala | 4 - .../java8/converterImpl/StepsRange.scala | 2 - .../java8/converterImpl/StepsString.scala | 3 - .../java8/converterImpl/StepsVector.scala | 1 - .../java8/converterImpl/StepsWithTail.scala | 1 - .../compat/java8/FunctionConvertersTest.scala | 88 +++++++++---------- .../compat/java8/StreamConvertersTest.scala | 2 + 37 files changed, 76 insertions(+), 124 deletions(-) diff --git a/build.sbt b/build.sbt index 2107029..ca970fc 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,8 @@ def osgiExport(scalaVersion: String, version: String) = { lazy val commonSettings = Seq( organization := "org.scala-lang.modules", - version := "0.9.0-SNAPSHOT" + version := "0.9.0-SNAPSHOT", + scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") ) lazy val fnGen = (project in file("fnGen")). diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 46779bc..46d79f3 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -14,7 +14,6 @@ object WrapFnGen { val packaging = "package scala.compat.java8" import scala.tools.nsc._ - import scala.reflect.internal._ val settings = new Settings(msg => sys.error(msg)) settings.usejavacp.value = true val compiler = new Global(settings) @@ -59,12 +58,12 @@ object WrapFnGen { } implicit class SplitMyLinesAndStuff(s: String) { - def toVec = s.linesIterator.toVector + def toVec = s.lines.toVector def nonBlank = s.trim.length > 0 } implicit class TreeToText(t: Tree) { - def text = showCode(t).replace("$", "").linesIterator.toVector + def text = showCode(t).replace("$", "").lines.toVector } case class Prioritized(lines: Vector[String], priority: Int) { @@ -253,7 +252,6 @@ object WrapFnGen { q"""@inline implicit def $s2jImpN[..$scalafnTdefs](sf: $scalaType[..$scalafnTnames])(implicit ..$evs): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf.asInstanceOf[$scalaType[..$scalaTargs]]) """ - val depth = numberedA.size (tree, tdParams.length) } @@ -290,7 +288,7 @@ object WrapFnGen { def sameText(f: java.io.File, text: String): Boolean = { val x = scala.io.Source.fromFile(f) val lines = try { x.getLines.toVector } finally { x.close } - lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) + lines.iterator.filter(_.nonBlank) == text.lines.filter(_.nonBlank) } def write(f: java.io.File, text: String) { diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 7dc047a..99f019a 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -3,11 +3,12 @@ */ package scala.compat.java8 +import scala.language.implicitConversions + import scala.concurrent.java8.FuturesConvertersImpl._ -import scala.concurrent.{ Future, Promise, ExecutionContext, ExecutionContextExecutorService, ExecutionContextExecutor, impl } -import java.util.concurrent.{ CompletionStage, Executor, ExecutorService, CompletableFuture } -import scala.util.{ Try, Success, Failure } -import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } +import scala.concurrent.{ Future, Promise, ExecutionContext, ExecutionContextExecutorService, ExecutionContextExecutor } +import java.util.concurrent.{ CompletionStage, Executor, ExecutorService } +import java.util.function.Consumer /** * This class contains static methods which convert between Java CompletionStage diff --git a/src/main/scala/scala/compat/java8/OptionConverters.scala b/src/main/scala/scala/compat/java8/OptionConverters.scala index f89dd22..75b7915 100644 --- a/src/main/scala/scala/compat/java8/OptionConverters.scala +++ b/src/main/scala/scala/compat/java8/OptionConverters.scala @@ -3,7 +3,6 @@ */ package scala.compat.java8 -import language.implicitConversions import java.util.{Optional, OptionalDouble, OptionalInt, OptionalLong} /** This class enables bidirectional conversion between `scala.Option` and the diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 617f9e5..9210010 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -3,7 +3,6 @@ */ package scala.compat.java8 -import language.implicitConversions import java.util.{ Iterator => JIterator, PrimitiveIterator } /** This class enables conversion from `scala.Iterator` to the set of diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index c6334a2..80f7077 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -1,6 +1,6 @@ package scala.compat.java8 -import language.implicitConversions +import scala.language.higherKinds import java.util.stream._ import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala index e67ca79..4f1eeb8 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -1,5 +1,7 @@ package scala.compat.java8.collectionImpl +import scala.language.higherKinds + /** An `Accumulator` is a low-level collection specialized for gathering * elements in parallel and then joining them in order by merging Accumulators. * Accumulators can contain more than `Int.MaxValue` elements. @@ -232,7 +234,7 @@ private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) exte private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index private var N = acc.totalSize - private def duplicateSelf(limit: Long = N): AccumulatorStepper[A] = { + private def duplicateSelf(limit: Long): AccumulatorStepper[A] = { val ans = new AccumulatorStepper(acc) ans.h = h ans.i = i @@ -249,7 +251,7 @@ private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) exte i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED + def characteristics() = ORDERED | SIZED | SUBSIZED def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index 07d6b42..65fabe6 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -1,5 +1,7 @@ package scala.compat.java8.collectionImpl +import scala.language.higherKinds + /** A `DoubleAccumulator` is a low-level collection specialized for gathering * elements in parallel and then joining them in order by merging them. * This is a manually specialized variant of `Accumulator` with no actual @@ -229,7 +231,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index private var N = acc.totalSize - private def duplicateSelf(limit: Long = N): DoubleAccumulatorStepper = { + private def duplicateSelf(limit: Long): DoubleAccumulatorStepper = { val ans = new DoubleAccumulatorStepper(acc) ans.h = h ans.i = i @@ -246,7 +248,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL + def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index 0747deb..129ed9b 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -1,5 +1,7 @@ package scala.compat.java8.collectionImpl +import scala.language.higherKinds + /** A `IntAccumulator` is a low-level collection specialized for gathering * elements in parallel and then joining them in order by merging them. * This is a manually specialized variant of `Accumulator` with no actual @@ -236,7 +238,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index private var N = acc.totalSize - private def duplicateSelf(limit: Long = N): IntAccumulatorStepper = { + private def duplicateSelf(limit: Long): IntAccumulatorStepper = { val ans = new IntAccumulatorStepper(acc) ans.h = h ans.i = i @@ -253,7 +255,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL + def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 285d275..1c4bdd3 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -1,5 +1,7 @@ package scala.compat.java8.collectionImpl +import scala.language.higherKinds + /** A `LongAccumulator` is a low-level collection specialized for gathering * elements in parallel and then joining them in order by merging them. * This is a manually specialized variant of `Accumulator` with no actual @@ -230,7 +232,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex private var n = if (acc.hIndex > 0) acc.cumulative(0) else acc.index private var N = acc.totalSize - private def duplicateSelf(limit: Long = N): LongAccumulatorStepper = { + private def duplicateSelf(limit: Long): LongAccumulatorStepper = { val ans = new LongAccumulatorStepper(acc) ans.h = h ans.i = i @@ -247,7 +249,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex i = 0 } - def characteristics = ORDERED | SIZED | SUBSIZED | NONNULL + def characteristics() = ORDERED | SIZED | SUBSIZED | NONNULL def estimateSize = N diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index aa9d6cd..a78d1f5 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,5 +1,7 @@ package scala.compat.java8.collectionImpl +import scala.language.higherKinds + import java.util.Spliterator /** A Stepper is a specialized collection that can step through its @@ -66,7 +68,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self: CC => * guaranteed to be any safer than modification of any generic mutable collection, and if the underlying collection is ordered by * virtue of sorting, `Stepper` will not keep track of that fact. */ - def characteristics: Int + def characteristics(): Int /** Returns the size of the collection, if known exactly, or `-1` if not. */ def knownSize: Long diff --git a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala index 2affeb9..cb3c963 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala @@ -1,9 +1,6 @@ package scala.compat.java8.converterImpl -import language.implicitConversions - import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ trait AccumulatesFromStepper[@specialized(Double, Int, Long) A, Acc <: AccumulatorLike[A, Acc]] { def apply(stepper: Stepper[A]): Acc diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index 017f2cd..e194de9 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -1,9 +1,6 @@ package scala.compat.java8.converterImpl -import language.implicitConversions - import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ trait MakesStepper[T, +Extra] extends Any { /** Generates a fresh stepper of type `S` for element type `T` */ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala index 566c17c..7fbf363 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala @@ -2,11 +2,6 @@ package scala.compat.java8.converterImpl import language.implicitConversions -import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ - trait Priority3StepConverters { implicit def richIterableCanStep[A](underlying: Iterable[A]) = new RichIterableCanStep(underlying) implicit def richMapCanStep[K, V](underlying: collection.Map[K, V]) = new RichMapCanStep[K, V](underlying) diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index ef75eb6..c9d21cf 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -1,10 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala index b6f698a..8b0a49c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import language.implicitConversions - import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index ec30008..8661105 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -1,6 +1,5 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala index dde431e..f4869d6 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -1,6 +1,5 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala index d6a5b0e..4875a4a 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -1,10 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala index abde687..84e0aff 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -1,12 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ ///////////////////////////// // Stepper implementations // diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index e36fab0..1065f0d 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -1,10 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala index dd8d6a3..b0d63e9 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -1,12 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ // Iterables just defer to iterator unless they can pattern match something better. // TODO: implement pattern matching! diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala index 02f58cd..d3b244f 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -1,12 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ ///////////////////////////// // Stepper implementations // diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala index f70b8b2..6f74880 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import annotation.tailrec - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala index 6f4d0c9..de4cdf1 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index d0b7419..ed5abfa 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala index 116e921..02a05c7 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala index 83609eb..8de1df0 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala index 6565dd8..eeda5b9 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -1,7 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator - import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index 892bed5..4c18398 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,10 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index 3a1f49c..1bf71fa 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,12 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ - -import Stepper._ // Generic maps defer to the iterator steppers if a more precise type cannot be found via pattern matching // TODO: implement pattern matching diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index 63505c8..d364ed2 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,10 +1,8 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index c8c7ad6..66101a1 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -1,9 +1,6 @@ package scala.compat.java8.converterImpl -import language.implicitConversions - import scala.compat.java8.collectionImpl._ -import scala.compat.java8.runtime._ import Stepper._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index ad54503..efbaa2d 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,6 +1,5 @@ package scala.compat.java8.converterImpl -import language.implicitConversions import scala.annotation.switch import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala index 0fcc12b..f9977d7 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -1,6 +1,5 @@ package scala.compat.java8.converterImpl -import java.util.Spliterator import scala.compat.java8.collectionImpl._ import Stepper._ diff --git a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala index 7e8f76d..d226ec6 100644 --- a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala @@ -33,8 +33,8 @@ class FunctionConvertersTest { val bic2 = new BiConsumer[Int, Long]{ def accept(i: Int, l: Long) { save((i,l)) } } val sbic = (s: String, f: File) => { save((s,f)); () } val zbic = (i: Int, l: Long) => { save((i,l)); () } - def jbic[A, B](bic: BiConsumer[A, B])(a: A, b: B) = { bic.accept(a,b); recall == (a,b) } - def fbic[A, B](f: (A,B) => Unit)(a: A, b: B) = { f(a,b); recall == (a,b) } + def jbic[A, B](bic: BiConsumer[A, B])(a: A, b: B) = { bic.accept(a,b); recall == ((a,b)) } + def fbic[A, B](f: (A,B) => Unit)(a: A, b: B) = { f(a,b); recall == ((a,b)) } assert(jbic(asJavaBiConsumer(sbic))(str, fyl)) assert(jbic(asJavaBiConsumer(zbic))(num, nmm)) assert(jbic(sbic.asJava)(str, fyl)) @@ -48,7 +48,7 @@ class FunctionConvertersTest { // BiFunction tests; conceptually narrows to any of the Bi functions or to ObjLongConsumer etc @Test - def test_BiFunction { + def test_BiFunction() { val bif1 = new BiFunction[String, File, (String, File)]{ def apply(s: String, f: File) = (s,f) } val bif2 = new BiFunction[Int, Long, Double]{ def apply(i: Int, l: Long) = i.toDouble*l } val sbif = (s: String, f: File) => (s,f) @@ -67,7 +67,7 @@ class FunctionConvertersTest { // BinaryOperator tests; actually widens to BiFunction and conceptually narrows to IntBinaryOperator etc. @Test - def test_BinaryOperator { + def test_BinaryOperator() { val bop1 = new BinaryOperator[String]{ def apply(s: String, t: String) = s + t } val bop2 = new BinaryOperator[Int]{ def apply(i: Int, j: Int) = i + j } val sbop = (s: String, t: String) => s + t @@ -86,7 +86,7 @@ class FunctionConvertersTest { // BiPredicate tests; conceptually widens to BiFunction. Does not narrow (no IntBiPredicate or the like). @Test - def test_BiPredicate { + def test_BiPredicate() { val bip1 = new BiPredicate[String, File]{ def test(s: String, f: File) = s == f.getName } val bip2 = new BiPredicate[Int, Long]{ def test(i: Int, l: Long) = i == l } val sbip = (s: String, f: File) => s == f.getName @@ -105,7 +105,7 @@ class FunctionConvertersTest { // BooleanSupplier tests; conceptually widens to Supplier and Function. @Test - def test_BooleanSupplier { + def test_BooleanSupplier() { val bsup = new BooleanSupplier{ def getAsBoolean = true } val sbup = () => true def foo(bs: BooleanSupplier) = bs.getAsBoolean @@ -119,7 +119,7 @@ class FunctionConvertersTest { // Consumer tests; conceptually widens to Function and narrows to IntConsumer etc. @Test - def test_Consumer { + def test_Consumer() { val con1 = new Consumer[String]{ def accept(s: String) { save(s) } } val con2 = new Consumer[Int]{ def accept(i: Int) { save(i) } } val scon = (s: String) => { save(s); () } @@ -138,7 +138,7 @@ class FunctionConvertersTest { // DoubleBinaryOperator tests; conceptually widens to BinaryOperator, ToDoubleBiFunction, and BiFunction @Test - def test_DoubleBinaryOperator { + def test_DoubleBinaryOperator() { val dbop = new DoubleBinaryOperator{ def applyAsDouble(a: Double, b: Double) = a*b } val sdbo = (a: Double, b: Double) => a*b def foo(dbo: DoubleBinaryOperator)(a: Double, b: Double) = dbo.applyAsDouble(a,b) @@ -152,7 +152,7 @@ class FunctionConvertersTest { // DoubleConsumer tests; conceptually widens to Consumer and Function @Test - def test_DoubleConsumer { + def test_DoubleConsumer() { val dcon = new DoubleConsumer{ def accept(value: Double) { save(value) } } val sdco = (d: Double) => { save(d); () } def jf(dc: DoubleConsumer)(d: Double) = { dc.accept(d); recall == d } @@ -165,7 +165,7 @@ class FunctionConvertersTest { // DoubleFunction tests; conceptually widens to Function, narrows to DoubleUnaryOperator and DoubleToIntFunction etc. @Test - def test_DoubleFunction { + def test_DoubleFunction() { val dfn1 = new DoubleFunction[String]{ def apply(value: Double) = f"$value%.3f" } val dfn2 = new DoubleFunction[Int]{ def apply(value: Double) = math.ceil(value).toInt } val sdfn = (d: Double) => f"$d%.3f" @@ -184,7 +184,7 @@ class FunctionConvertersTest { // DoublePredicate tests; conceptually widens to DoubleFunction, Predicate, and Function @Test - def test_DoublePredicate { + def test_DoublePredicate() { val dprd = new DoublePredicate{ def test(value: Double) = value > 0 } val sdpr = (d: Double) => d > 0 def foo(dp: DoublePredicate)(d: Double) = dp.test(d) @@ -198,7 +198,7 @@ class FunctionConvertersTest { // DoubleSupplier tests; conceptually widens to Supplier and Function @Test - def test_DoubleSupplier { + def test_DoubleSupplier() { val dsup = new DoubleSupplier{ def getAsDouble = 22.0/7 } val sdsu = () => 22.0/7 def foo(ds: DoubleSupplier) = ds.getAsDouble @@ -212,7 +212,7 @@ class FunctionConvertersTest { // DoubleToIntFunction tests; conceptually widens to DoubleFunction and Function @Test - def test_DoubleToIntFunction { + def test_DoubleToIntFunction() { val d2if = new DoubleToIntFunction{ def applyAsInt(value: Double) = math.ceil(value).toInt } val sd2i = (d: Double) => math.ceil(d).toInt def foo(di: DoubleToIntFunction)(d: Double) = di.applyAsInt(d) @@ -226,7 +226,7 @@ class FunctionConvertersTest { // DoubleToLongFunction tests; conceptually widens to DoubleFunction and Function @Test - def test_DoubleToLongFunction { + def test_DoubleToLongFunction() { val d2lf = new DoubleToLongFunction{ def applyAsLong(value: Double) = java.lang.Double.doubleToRawLongBits(value) } val sd2l = (d: Double) => java.lang.Double.doubleToRawLongBits(d) def foo(dl: DoubleToLongFunction)(d: Double) = dl.applyAsLong(d) @@ -240,7 +240,7 @@ class FunctionConvertersTest { // DoubleUnaryOperator tests; conceptually widens to DoubleFunction and ToDoubleFunction and Function @Test - def test_DoubleUnaryOperator { + def test_DoubleUnaryOperator() { val duop = new DoubleUnaryOperator{ def applyAsDouble(value: Double) = 1.0 - value } val sduo = (d: Double) => 1.0 - d def foo(du: DoubleUnaryOperator)(d: Double) = du.applyAsDouble(d) @@ -254,7 +254,7 @@ class FunctionConvertersTest { // Function tests; conceptually narrows to everything except BiFunction and its conceptual subclasses @Test - def test_Function { + def test_Function() { val fun1 = new Function[String, File]{ def apply(s: String): File = new File(s) } val fun2 = new Function[Int, Long]{ def apply(i: Int): Long = ((i.toLong)<<32) | i } def sfun = (s: String) => new File(s) @@ -283,7 +283,7 @@ class FunctionConvertersTest { // IntBinaryOperator tests; conceptually widens to BinaryOperator, ToIntBiFunction, and BiFunction @Test - def test_IntBinaryOperator { + def test_IntBinaryOperator() { val ibop = new IntBinaryOperator{ def applyAsInt(a: Int, b: Int) = a ^ b } val sibo = (i: Int, j: Int) => i ^ j def foo(ibo: IntBinaryOperator)(a: Int, b: Int) = ibo.applyAsInt(a,b) @@ -297,7 +297,7 @@ class FunctionConvertersTest { // IntConsumer tests; conceptually widens to Consumer and Function @Test - def test_IntConsumer { + def test_IntConsumer() { val icon = new IntConsumer{ def accept(i: Int) { save(i) } } val sico = (i: Int) => { save(i); () } def jf(ic: IntConsumer)(d: Int) = { ic.accept(d); recall == d } @@ -310,7 +310,7 @@ class FunctionConvertersTest { // IntFunction tests; conceptually widens to Function @Test - def test_IntFunction { + def test_IntFunction() { val ifn1 = new IntFunction[String]{ def apply(i: Int) = "!"*i } val ifn2 = new IntFunction[Long]{ def apply(i: Int) = ((i.toLong) << 32) | i } val sifn = (i: Int) => "!"*i @@ -329,7 +329,7 @@ class FunctionConvertersTest { // IntPredicate tests; conceptually widens to IntFunction, Predicate, and Function @Test - def test_IntPredicate { + def test_IntPredicate() { val iprd = new IntPredicate{ def test(i: Int) = i < 0 } val sipr = (i: Int) => i < 0 def foo(ip: IntPredicate)(d: Int) = ip.test(d) @@ -343,7 +343,7 @@ class FunctionConvertersTest { // IntSupplier tests; conceptually widens to Supplier and Function @Test - def test_IntSupplier { + def test_IntSupplier() { val isup = new IntSupplier{ def getAsInt = 42 } val sisu = () => 42 def foo(ds: IntSupplier) = ds.getAsInt @@ -357,7 +357,7 @@ class FunctionConvertersTest { // IntToDoubleFunction tests; conceptually widens to ToDoubleFunction, IntFunction, and Function @Test - def test_IntToDoubleFunction { + def test_IntToDoubleFunction() { val i2df = new IntToDoubleFunction{ def applyAsDouble(i: Int) = i + 0.1*i } def si2d = (i: Int) => i + 0.1*i def foo(id: IntToDoubleFunction)(i: Int) = id.applyAsDouble(i) @@ -371,7 +371,7 @@ class FunctionConvertersTest { // IntToLongFunction tests; conceptually widens to ToLongFunction, IntFunction, and Function @Test - def test_IntToLongFunction { + def test_IntToLongFunction() { val i2lf = new IntToLongFunction { def applyAsLong(i: Int) = (i.toLong << 32) | i } val si2l = (i: Int) => (i.toLong << 32) | i def foo(il: IntToLongFunction)(d: Int) = il.applyAsLong(d) @@ -385,7 +385,7 @@ class FunctionConvertersTest { // IntUnaryOperator tests; conceptually widens to ToIntFunction, IntFunction, and Function @Test - def test_IntUnaryOperator { + def test_IntUnaryOperator() { val iuop = new IntUnaryOperator{ def applyAsInt(i: Int) = ~i } val siuo = (i: Int) => ~i def foo(iu: IntUnaryOperator)(d: Int) = iu.applyAsInt(d) @@ -399,7 +399,7 @@ class FunctionConvertersTest { // LongBinaryOperator tests; conceptually widens to ToLongFunction, LongFunction, and Function @Test - def test_LongBinaryOperator{ + def test_LongBinaryOperator() { val lbop = new LongBinaryOperator{ def applyAsLong(a: Long, b: Long) = a | b } val slbo = (a: Long, b: Long) => a | b def foo(lbo: LongBinaryOperator)(a: Long, b: Long) = lbo.applyAsLong(a,b) @@ -413,7 +413,7 @@ class FunctionConvertersTest { // LongConsumer tests; conceptually widens to Consumer and Function @Test - def test_LongConsumer { + def test_LongConsumer() { val lcon = new LongConsumer{ def accept(l: Long) { save(l) } } val slco = (l: Long) => { save(l); () } def jf(lc: LongConsumer)(d: Long) = { lc.accept(d); recall == d } @@ -426,7 +426,7 @@ class FunctionConvertersTest { // LongFunction tests; conceptually widens to Function @Test - def test_LongFunction { + def test_LongFunction() { val lfn1 = new LongFunction[String]{ def apply(l: Long) = l.toString } val lfn2 = new LongFunction[Int]{ def apply(l: Long) = (l & 0xFFFFFF).toInt } val slfn = (l: Long) => l.toString @@ -445,7 +445,7 @@ class FunctionConvertersTest { // LongPredicate tests; conceptually widens to LongFunction and Predicate and Function @Test - def test_LongPredicate { + def test_LongPredicate() { val lprd = new LongPredicate{ def test(l: Long) = l < 1 } val slpr = (l: Long) => l < 1 def foo(lp: LongPredicate)(d: Long) = lp.test(d) @@ -459,7 +459,7 @@ class FunctionConvertersTest { // LongSupplier tests; conceptually widens to ToLongFunction and Supplier and Function @Test - def test_LongSupplier { + def test_LongSupplier() { val lsup = new LongSupplier{ def getAsLong = 1000000000000L } val slsu = () => 1000000000000L def foo(ls: LongSupplier) = ls.getAsLong @@ -473,7 +473,7 @@ class FunctionConvertersTest { // LongToDoubleFunction tests; conceptually widens to ToDoubleFunction, LongFunction, and Function @Test - def test_LongToDoubleFunction { + def test_LongToDoubleFunction() { val l2df = new LongToDoubleFunction{ def applyAsDouble(l: Long) = l + 1e-4*l } def sl2d = (l: Long) => l + 1e-4*l def foo(ld: LongToDoubleFunction)(l: Long) = ld.applyAsDouble(l) @@ -487,7 +487,7 @@ class FunctionConvertersTest { // LongToIntFunction tests; conceptually widens to ToIntFunction, LongFunction, and Function @Test - def test_LongToIntFunction { + def test_LongToIntFunction() { val l2if = new LongToIntFunction{ def applyAsInt(l :Long) = (l & 0xFFFFFF).toInt } val sl2i = (l: Long) => (l & 0xFFFFFF).toInt def foo(li: LongToIntFunction)(l: Long) = li.applyAsInt(l) @@ -501,7 +501,7 @@ class FunctionConvertersTest { // LongUnaryOperator tests; conceptually widens to LongFunction, ToLongFunction, and Function @Test - def test_LongUnaryOperator { + def test_LongUnaryOperator() { val luop = new LongUnaryOperator{ def applyAsLong(l: Long) = -l } val sluo = (l: Long) => -l def foo(du: LongUnaryOperator)(l: Long) = du.applyAsLong(l) @@ -515,7 +515,7 @@ class FunctionConvertersTest { // ObjDoubleConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjDoubleConsumer { + def test_ObjDoubleConsumer() { val odc1 = new ObjDoubleConsumer[String]{ def accept(s: String, d: Double) { save((s,d)) } } val odc2 = new ObjDoubleConsumer[Int]{ def accept(i: Int, d: Double) { save((i,d)) } } val sodc = (s: String, d: Double) => { save((s,d)); () } @@ -540,7 +540,7 @@ class FunctionConvertersTest { // ObjIntConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjIntConsumer { + def test_ObjIntConsumer() { val oic1 = new ObjIntConsumer[String]{ def accept(s: String, i: Int) { save((s,i)) } } val oic2 = new ObjIntConsumer[Int]{ def accept(j: Int, i: Int) { save((j,i)) } } val soic = (s: String, i: Int) => { save((s,i)); () } @@ -565,7 +565,7 @@ class FunctionConvertersTest { // ObjLongConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjLongConsumer { + def test_ObjLongConsumer() { val olc1 = new ObjLongConsumer[String]{ def accept(s: String, l: Long) { save((s,l)) } } val olc2 = new ObjLongConsumer[Int]{ def accept(i: Int, l: Long) { save((i,l)) } } val solc = (s: String, l: Long) => { save((s,l)); () } @@ -590,7 +590,7 @@ class FunctionConvertersTest { // Predicate tests; conceptually widens to Function and narrows to IntPredicate etc. @Test - def test_Predicate { + def test_Predicate() { val prd1 = new Predicate[String]{ def test(s: String) = s.isEmpty } val prd2 = new Predicate[Int]{ def test(i: Int) = i < 0 } def sprd = (s: String) => s.isEmpty @@ -612,7 +612,7 @@ class FunctionConvertersTest { // Supplier tests; conceptually widens to Function and narrows to IntSupplier etc. @Test - def test_Supplier { + def test_Supplier() { val sup1 = new Supplier[String]{ def get = "halibut" } val sup2 = new Supplier[Int]{ def get = 17 } val ssup = () => "halibut" @@ -636,7 +636,7 @@ class FunctionConvertersTest { // ToDoubleBiFunction tests; conceptually widens to BiFunction and narrows to DoubleBinaryOperator @Test - def test_ToDoubleBiFunction { + def test_ToDoubleBiFunction() { { val bfd1 = new ToDoubleBiFunction[String, File]{ def applyAsDouble(s: String, f: File) = s.length.toDouble * f.getName.length } val sbfd = (s: String, f: File) => s.length.toDouble * f.getName.length @@ -666,7 +666,7 @@ class FunctionConvertersTest { // ToDoubleFunction tests; conceptually widens to Function and narrows to DoubleUnaryOperator, IntToDoubleFunction, etc. @Test - def test_ToDoubleFunction { + def test_ToDoubleFunction() { { val fnd1 = new ToDoubleFunction[String]{ def applyAsDouble(s: String) = s.length / (s.headOption.getOrElse(0: Char)+1).toDouble } val sfnd = (s: String) => s.length / (s.headOption.getOrElse(0: Char)+1).toDouble @@ -694,7 +694,7 @@ class FunctionConvertersTest { // ToIntBiFunction tests; conceptually widens to BiFunction and narrows to IntBinaryOperator @Test - def test_ToIntBiFunction { + def test_ToIntBiFunction() { { val bfi1 = new ToIntBiFunction[String, File]{ def applyAsInt(s: String, f: File) = s.length + f.getName.length } val sbfi = (s: String, f: File) => s.length.toInt + f.getName.length @@ -723,7 +723,7 @@ class FunctionConvertersTest { // ToIntFunction tests; conceptually widens to Function and narrows to IntUnaryOperator, etc.. @Test - def test_ToIntFunction { + def test_ToIntFunction() { { val fni1 = new ToIntFunction[String]{ def applyAsInt(s: String) = s.length } val sfni = (s: String) => s.length @@ -751,7 +751,7 @@ class FunctionConvertersTest { // ToLongBiFunction tests; conceptually widens to BiFunction and narrows to LongBinaryOperator @Test - def test_ToLongBiFunction{ + def test_ToLongBiFunction() { { val bfl1 = new ToLongBiFunction[String, File]{ def applyAsLong(s: String, f: File) = s.length * f.getName.length } val sbfl = (s: String, f: File) => s.length.toLong * f.getName.length @@ -780,7 +780,7 @@ class FunctionConvertersTest { // ToLongFunction tests; conceptually widens to Function and narrows to LongUnaryOperator, LongToIntFunction etc.. @Test - def test_ToLongFunction { + def test_ToLongFunction() { { val fnl1 = new ToLongFunction[String]{ def applyAsLong(s: String) = s.length.toLong << 16 } val sfnl = (s: String) => s.length.toLong << 16 @@ -808,7 +808,7 @@ class FunctionConvertersTest { // UnaryOperator tests; actually widens to Function and conceptually narrows to IntUnaryOperator etc.. @Test - def test_UnaryOperator { + def test_UnaryOperator() { { val uop1 = new UnaryOperator[String]{ def apply(s: String) = s.toUpperCase } val suop = (s: String) => s.toUpperCase diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index 26ca38c..d3131a6 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -1,5 +1,7 @@ package scala.compat.java8 +import scala.language.higherKinds + import org.junit.Test import org.junit.Assert._ From 978a6eeb6df1b40bb6a51b6306d947b272e22969 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 20 Jun 2017 14:19:45 -0700 Subject: [PATCH 123/340] upgrade Scala (2.11.8->11, 2.12.0->2) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ca970fc..9bd553c 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.0", "2.11.8", "2.13.0-M1").map(_ -> true) + 8 -> List("2.12.2", "2.11.11", "2.13.0-M1").map(_ -> true) ) val disableDocs = sys.props("nodocs") == "true" From 0b48564f8baee00245260018a58d732e4631aaff Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 24 Jul 2017 13:42:40 -0700 Subject: [PATCH 124/340] in build, avoid method deprecated in sbt 0.13.16 toError is deprecated now. the replacement code is as recommended by the deprecation message --- build.sbt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9bd553c..dcabb6c 100644 --- a/build.sbt +++ b/build.sbt @@ -65,7 +65,8 @@ lazy val root = (project in file(".")). val args = (new File(canon, "FunctionConverters.scala")).toString :: Nil val runTarget = (mainClass in Compile in fnGen).value getOrElse "No main class defined for function conversion generator" val classPath = (fullClasspath in Compile in fnGen).value - toError(runner.value.run(runTarget, classPath.files, args, streams.value.log)) + runner.value.run(runTarget, classPath.files, args, streams.value.log) + .foreach(sys.error) (out ** "*.scala").get }.taskValue, From 3b22c7c58e2931963500bd53bbf736eeb25961f2 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 5 Aug 2017 21:27:02 -0400 Subject: [PATCH 125/340] Scala 2.13.0-M2, plus other version bumps 2.11.8->11, 2.12.0->3, sbt 0.13.15->16 scala-sbt-module 1.0.8 -> 1.0.12 upgrade all the things. the past is past. the future is glorious. --- benchmark/build.sbt | 4 ++-- build.sbt | 2 +- project/build.properties | 2 +- project/plugins.sbt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmark/build.sbt b/benchmark/build.sbt index 79900aa..0703b42 100644 --- a/benchmark/build.sbt +++ b/benchmark/build.sbt @@ -5,8 +5,8 @@ val parseJmh = TaskKey[Unit]("parseJmh", "Parses JMH benchmark logs in results/j lazy val root = (project in file(".")).settings( name := "java8-compat-bench", - scalaVersion := "2.11.8", - crossScalaVersions := List("2.11.8" /* TODO, "2.12.0-M4"*/), + scalaVersion := "2.11.11", + crossScalaVersions := List("2.11.11" /* TODO, "2.12.0-M4"*/), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.9.0-SNAPSHOT.jar"), diff --git a/build.sbt b/build.sbt index dcabb6c..1874deb 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.2", "2.11.11", "2.13.0-M1").map(_ -> true) + 8 -> List("2.12.3", "2.11.11", "2.13.0-M2").map(_ -> true) ) val disableDocs = sys.props("nodocs") == "true" diff --git a/project/build.properties b/project/build.properties index 64317fd..c091b86 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.15 +sbt.version=0.13.16 diff --git a/project/plugins.sbt b/project/plugins.sbt index 36ce0ab..63c587e 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ scalacOptions += "-Xfatal-warnings" -addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.8") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.12") From f41d58ecec8c5b278557a1994c232a4f4c5425ce Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Thu, 7 Dec 2017 01:41:14 -0500 Subject: [PATCH 126/340] Scala 2.12.3 -> 2.12.4 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1874deb..3899b1e 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.3", "2.11.11", "2.13.0-M2").map(_ -> true) + 8 -> List("2.12.4", "2.11.11", "2.13.0-M2").map(_ -> true) ) val disableDocs = sys.props("nodocs") == "true" From a3467b66cbb25c81be5ecc8b813e80c7f487db51 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 16 Feb 2018 07:50:51 -0800 Subject: [PATCH 127/340] bump Scala versions --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3899b1e..f0e9ad4 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.4", "2.11.11", "2.13.0-M2").map(_ -> true) + 8 -> List("2.12.4", "2.11.12", "2.13.0-M3").map(_ -> true) ) val disableDocs = sys.props("nodocs") == "true" From 7e7eb69ef38f422ae673f27a25963b7363f04825 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 16 Feb 2018 07:51:43 -0800 Subject: [PATCH 128/340] bump sbt version, plugin version, copyright year --- LICENSE | 4 ++-- project/build.properties | 2 +- project/plugins.sbt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index 6fdcc0c..d536dec 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2002-2017 EPFL -Copyright (c) 2011-2017 Lightbend, Inc. +Copyright (c) 2002-2018 EPFL +Copyright (c) 2011-2018 Lightbend, Inc. All rights reserved. diff --git a/project/build.properties b/project/build.properties index c091b86..133a8f1 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 +sbt.version=0.13.17 diff --git a/project/plugins.sbt b/project/plugins.sbt index 63c587e..26dd0ea 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ scalacOptions += "-Xfatal-warnings" -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.12") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.13") From 35831f444ca3acb214c9a276867d3a1e06d1a940 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 16 Feb 2018 07:59:01 -0800 Subject: [PATCH 129/340] gah, the genjavadoc version for 2.13.0-M3 is 0.11 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f0e9ad4..0b3721a 100644 --- a/build.sbt +++ b/build.sbt @@ -115,7 +115,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.10" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.11" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From 1912814cb893a4a55c3e5b526afe87a4a26de4ad Mon Sep 17 00:00:00 2001 From: NthPortal Date: Wed, 21 Feb 2018 22:54:56 -0500 Subject: [PATCH 130/340] Remove override of `Future.onSuccess` --- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 0c5bf49..61a2a6a 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -87,8 +87,6 @@ object FuturesConvertersImpl { } class P[T](val wrapped: CompletionStage[T]) extends DefaultPromise[T] with BiConsumer[T, Throwable] { - override def onSuccess[U](pf: PartialFunction[T, U])(implicit executor: ExecutionContext): Unit = super.onSuccess(pf) - override def accept(v: T, e: Throwable): Unit = { if (e == null) complete(Success(v)) else complete(Failure(e)) From a5fcf5f6ac28de7cf6a9c70447bc83574977a163 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 22 Mar 2018 15:32:10 -0400 Subject: [PATCH 131/340] support building on Java 9 and 10 because we're trying to get the Scala 2.12 community build up and running on Java 9 and beyond --- build.sbt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 0b3721a..4dbf529 100644 --- a/build.sbt +++ b/build.sbt @@ -1,8 +1,9 @@ import ScalaModulePlugin._ -scalaVersionsByJvm in ThisBuild := Map( - 8 -> List("2.12.4", "2.11.12", "2.13.0-M3").map(_ -> true) -) +scalaVersionsByJvm in ThisBuild := { + val versions = List("2.12.4", "2.11.12", "2.13.0-M3").map(_ -> true) + Map(8 -> versions, 9 -> versions, 10 -> versions) +} val disableDocs = sys.props("nodocs") == "true" From 855ff24013e0e7a13259c3fa6064020a33bbaaa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andre=CC=81n?= Date: Sun, 22 Jan 2017 14:15:40 +0100 Subject: [PATCH 132/340] Duration converters #85 --- .../compat/java8/DurationConverters.scala | 61 ++++++++++ .../compat/java8/DurationConvertersTest.scala | 112 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 src/main/scala/scala/compat/java8/DurationConverters.scala create mode 100644 src/test/scala/scala/compat/java8/DurationConvertersTest.scala diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala new file mode 100644 index 0000000..c6548f4 --- /dev/null +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012-2017 Typesafe Inc. + */ +package scala.compat.java8 + +import java.time.temporal.ChronoUnit +import java.util.concurrent.TimeUnit +import java.time.{Duration => JavaDuration} + +import scala.concurrent.duration.{FiniteDuration, Duration => ScalaDuration} + + +/** + * This class contains static methods which convert between Java Durations + * and the durations from the Scala concurrency package. This is useful when mediating between Scala and Java + * libraries with asynchronous APIs where timeouts for example are often expressed as durations. + */ +object DurationConverters { + + /** + * Transform a Java duration into a Scala duration. If the nanosecond part of the Java duration is zero the returned + * duration will have a time unit of seconds and if there is a nanoseconds part the Scala duration will have a time + * unit of nanoseconds. + * + * @throws IllegalArgumentException If the given Java Duration is out of bounds of what can be expressed with the + * Scala Durations. + */ + final def toScala(duration: java.time.Duration): scala.concurrent.duration.Duration = { + if (duration.getNano == 0) { + if (duration.getSeconds == 0) ScalaDuration.Zero + else FiniteDuration(duration.getSeconds, TimeUnit.SECONDS) + } else { + FiniteDuration( + duration.getSeconds * 1000000000 + duration.getNano, + TimeUnit.NANOSECONDS + ) + } + } + + /** + * Transform a Scala duration into a Java duration. Note that the Scala duration keeps the time unit it was created + * with while a Java duration always is a pair of seconds and nanos, so the unit it lost. + * + * @throws IllegalArgumentException If the Scala duration express a amount of time for the time unit that + * a Java Duration can not express (infinite durations and undefined durations) + */ + final def toJava(duration: scala.concurrent.duration.Duration): java.time.Duration = { + require(duration.isFinite(), s"Got [$duration] but only finite Scala durations can be expressed as a Java Durations") + if (duration.length == 0) JavaDuration.ZERO + else duration.unit match { + case TimeUnit.NANOSECONDS => JavaDuration.ofNanos(duration.length) + case TimeUnit.MICROSECONDS => JavaDuration.of(duration.length, ChronoUnit.MICROS) + case TimeUnit.MILLISECONDS => JavaDuration.ofMillis(duration.length) + case TimeUnit.SECONDS => JavaDuration.ofSeconds(duration.length) + case TimeUnit.MINUTES => JavaDuration.ofMinutes(duration.length) + case TimeUnit.HOURS => JavaDuration.ofHours(duration.length) + case TimeUnit.DAYS => JavaDuration.ofDays(duration.length) + } + } + +} diff --git a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala new file mode 100644 index 0000000..7d2d3dd --- /dev/null +++ b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2009-2017 Lightbend Inc. + */ +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ +import java.time.{Duration => JavaDuration} + +import scala.util.Try + +class DurationConvertersTest { + + import DurationConverters._ + import scala.concurrent.duration._ + + @Test + def scalaNanosToJavaDuration(): Unit = { + Seq[(Long, (Long, Int))]( + (Long.MinValue + 1) -> (-9223372037L, 145224193), // because java duration nanos are offset from the "wrong" direction + -1000000001L -> (-2, 999999999), + -1L -> (-1, 999999999), + 0L -> (0, 0), + 1L -> (0, 1), + 1000000001L -> (1,1), + Long.MaxValue -> (9223372036L, 854775807) + ).foreach { case (n, (expSecs, expNanos)) => + val result = toJava(n.nanos) + assertEquals(s"toJava($n nanos) -> $expSecs s)", expSecs, result.getSeconds) + assertEquals(s"toJava($n nanos) -> $expNanos n)", expNanos, result.getNano) + } + } + + @Test + def scalaMilliSecondsToJavaDuration(): Unit = { + Seq[(Long, (Long, Int))]( + -9223372036854L -> (-9223372037L, 146000000), + -1L -> (-1L, 999000000), + 0L -> (0L, 0), + 1L -> (0L, 1000000), + 9223372036854L -> (9223372036L, 854000000) + ).foreach { case (n, (expSecs, expNanos)) => + val result = toJava(n.millis) + assertEquals(s"toJava($n millis) -> $expSecs s)", expSecs, result.getSeconds) + assertEquals(s"toJava($n millis) -> $expNanos n)", expNanos, result.getNano) + } + } + + @Test + def scalaMicroSecondsToJavaDuration(): Unit = { + Seq[(Long, (Long, Int))]( + -9223372036854775L -> (-9223372037L, 145225000), + -1L -> (-1L, 999999000), + 0L -> (0L, 0), + 1L -> (0L, 1000), + 9223372036854775L -> (9223372036L, 854775000) + ).foreach { case (n, (expSecs, expNanos)) => + val result = toJava(n.micros) + assertEquals(s"toJava($n micros) -> $expSecs s)", expSecs, result.getSeconds) + assertEquals(s"toJava($n micros) -> $expNanos n)", expNanos, result.getNano) + } + } + + @Test + def scalaSecondsToJavaDuration(): Unit = { + Seq[(Long, (Long, Int))]( + -9223372036L -> (-9223372036L, 0), + -1L -> (-1L, 0), + 0L -> (0L, 0), + 1L -> (1L, 0), + 9223372036L -> (9223372036L, 0) + ).foreach { case (n, (expSecs, expNanos)) => + val result = toJava(n.seconds) + assertEquals(expSecs, result.getSeconds) + assertEquals(expNanos, result.getNano) + } + } + + + @Test + def javaSecondsToScalaDuration(): Unit = { + Seq[Long](-9223372036L, -1L, 0L, 1L, 9223372036L).foreach { n => + assertEquals(n, toScala(JavaDuration.ofSeconds(n)).toSeconds) + } + } + + + @Test + def javaNanosPartToScalaDuration(): Unit = { + Seq[Long](Long.MinValue + 1L, -1L, 0L, 1L, Long.MaxValue).foreach { n => + assertEquals(n, toScala(JavaDuration.ofNanos(n)).toNanos) + } + } + + @Test + def unsupportedScalaDurationThrows(): Unit = { + Seq(Duration.Inf, Duration.MinusInf, Duration.Undefined).foreach { d => + val res = Try { toJava(d) } + assertTrue(s"Expected exception for $d but got success", res.isFailure) + } + } + + @Test + def unsupportedJavaDurationThrows(): Unit = { + Seq(JavaDuration.ofSeconds(-9223372037L), JavaDuration.ofSeconds(9223372037L)).foreach { d => + val res = Try { toScala(d) } + assertTrue(s"Expected exception for $d but got success", res.isFailure) + } + } + + +} From b9813cb4b855f8a22b919f1f5ad84857cc086b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Mon, 30 Apr 2018 11:32:14 +0200 Subject: [PATCH 133/340] Test coverage using API from Java, entry in README, more correct overflow handling --- README.md | 31 ++++++++++++ .../compat/java8/DurationConverters.scala | 48 +++++++++++++------ .../java8/DurationConvertersJavaTest.java | 22 +++++++++ .../compat/java8/DurationConvertersTest.scala | 24 ++++------ 4 files changed, 95 insertions(+), 30 deletions(-) create mode 100644 src/test/java/scala/compat/java8/DurationConvertersJavaTest.java diff --git a/README.md b/README.md index 87543d8..acd7d53 100644 --- a/README.md +++ b/README.md @@ -253,3 +253,34 @@ public class StreamConvertersExample { } } ``` + +## Converters between `scala.concurrent.duration.FiniteDuration` and `java.time.Duration` + +Interconversion between Java's standard `java.time.Duration` type +and the `scala.concurrent.duration.FiniteDuration` types. The Java `Duration` does +not contain a time unit, so when converting from `FiniteDuration` the time unit used +to create it is lost. + +For the opposite conversion a `Duration` can potentially express a larger time span than +a `FiniteDuration`, for such cases an exception is thrown. + +Example of conversions from the Java type ways: + +```scala +import scala.concurrent.duration._ +import scala.compat.java8.DurationConverters + +val javaDuration: java.time.Duration = 5.seconds.toJava +val finiteDuration: FiniteDuration = javaDuration.toScala +``` + +From Java: +```java +import scala.compat.java8.DurationConverters; +import scala.concurrent.duration.FiniteDuration; + +DurationConverters.toScala(Duration.of(5, ChronoUnit.SECONDS)); +DurationConverters.toJava(FiniteDuration.create(5, TimeUnit.SECONDS)); +``` + + diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala index c6548f4..55a3720 100644 --- a/src/main/scala/scala/compat/java8/DurationConverters.scala +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -23,29 +23,33 @@ object DurationConverters { * unit of nanoseconds. * * @throws IllegalArgumentException If the given Java Duration is out of bounds of what can be expressed with the - * Scala Durations. + * Scala FiniteDuration. */ - final def toScala(duration: java.time.Duration): scala.concurrent.duration.Duration = { - if (duration.getNano == 0) { - if (duration.getSeconds == 0) ScalaDuration.Zero - else FiniteDuration(duration.getSeconds, TimeUnit.SECONDS) + final def toScala(duration: java.time.Duration): scala.concurrent.duration.FiniteDuration = { + val originalSeconds = duration.getSeconds + val originalNanos = duration.getNano + if (originalNanos == 0) { + if (originalSeconds == 0) ScalaDuration.Zero + else FiniteDuration(originalSeconds, TimeUnit.SECONDS) + } else if (originalSeconds == 0) { + FiniteDuration(originalNanos, TimeUnit.NANOSECONDS) } else { - FiniteDuration( - duration.getSeconds * 1000000000 + duration.getNano, - TimeUnit.NANOSECONDS - ) + try { + val secondsAsNanos = Math.multiplyExact(originalSeconds, 1000000000) + val totalNanos = secondsAsNanos + originalNanos + if ((totalNanos < 0 && secondsAsNanos < 0) || (totalNanos > 0 && secondsAsNanos > 0)) FiniteDuration(totalNanos, TimeUnit.NANOSECONDS) + else throw new ArithmeticException() + } catch { + case _: ArithmeticException => throw new IllegalArgumentException(s"Java duration $duration cannot be expressed as a Scala duration") + } } } /** - * Transform a Scala duration into a Java duration. Note that the Scala duration keeps the time unit it was created + * Transform a Scala FiniteDuration into a Java duration. Note that the Scala duration keeps the time unit it was created * with while a Java duration always is a pair of seconds and nanos, so the unit it lost. - * - * @throws IllegalArgumentException If the Scala duration express a amount of time for the time unit that - * a Java Duration can not express (infinite durations and undefined durations) */ - final def toJava(duration: scala.concurrent.duration.Duration): java.time.Duration = { - require(duration.isFinite(), s"Got [$duration] but only finite Scala durations can be expressed as a Java Durations") + final def toJava(duration: scala.concurrent.duration.FiniteDuration): java.time.Duration = { if (duration.length == 0) JavaDuration.ZERO else duration.unit match { case TimeUnit.NANOSECONDS => JavaDuration.ofNanos(duration.length) @@ -58,4 +62,18 @@ object DurationConverters { } } + implicit final class DurationOps(val duration: java.time.Duration) extends AnyVal { + /** + * See [[DurationConverters.toScala]] + */ + def toScala: scala.concurrent.duration.FiniteDuration = DurationConverters.toScala(duration) + } + + implicit final class FiniteDurationops(val duration: scala.concurrent.duration.FiniteDuration) extends AnyVal { + /** + * See [[DurationConverters.toJava]] + */ + def toJava: java.time.Duration = DurationConverters.toJava(duration) + } + } diff --git a/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java b/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java new file mode 100644 index 0000000..a032ae9 --- /dev/null +++ b/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2012-2018 Lightbend Inc. + */ +package scala.compat.java8; + +import org.junit.Test; +import scala.concurrent.duration.FiniteDuration; +import scala.runtime.java8.*; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.TimeUnit; + +public class DurationConvertersJavaTest { + + @Test + public void apiAccessibleFromJava() { + DurationConverters.toScala(Duration.of(5, ChronoUnit.SECONDS)); + DurationConverters.toJava(FiniteDuration.create(5, TimeUnit.SECONDS)); + } + +} \ No newline at end of file diff --git a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala index 7d2d3dd..9ce09c1 100644 --- a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala @@ -3,10 +3,11 @@ */ package scala.compat.java8 -import org.junit.Test -import org.junit.Assert._ import java.time.{Duration => JavaDuration} +import org.junit.Assert._ +import org.junit.Test + import scala.util.Try class DurationConvertersTest { @@ -25,7 +26,7 @@ class DurationConvertersTest { 1000000001L -> (1,1), Long.MaxValue -> (9223372036L, 854775807) ).foreach { case (n, (expSecs, expNanos)) => - val result = toJava(n.nanos) + val result = n.nanos.toJava assertEquals(s"toJava($n nanos) -> $expSecs s)", expSecs, result.getSeconds) assertEquals(s"toJava($n nanos) -> $expNanos n)", expNanos, result.getNano) } @@ -40,7 +41,7 @@ class DurationConvertersTest { 1L -> (0L, 1000000), 9223372036854L -> (9223372036L, 854000000) ).foreach { case (n, (expSecs, expNanos)) => - val result = toJava(n.millis) + val result = n.millis.toJava assertEquals(s"toJava($n millis) -> $expSecs s)", expSecs, result.getSeconds) assertEquals(s"toJava($n millis) -> $expNanos n)", expNanos, result.getNano) } @@ -55,7 +56,7 @@ class DurationConvertersTest { 1L -> (0L, 1000), 9223372036854775L -> (9223372036L, 854775000) ).foreach { case (n, (expSecs, expNanos)) => - val result = toJava(n.micros) + val result = n.micros.toJava assertEquals(s"toJava($n micros) -> $expSecs s)", expSecs, result.getSeconds) assertEquals(s"toJava($n micros) -> $expNanos n)", expNanos, result.getNano) } @@ -70,7 +71,7 @@ class DurationConvertersTest { 1L -> (1L, 0), 9223372036L -> (9223372036L, 0) ).foreach { case (n, (expSecs, expNanos)) => - val result = toJava(n.seconds) + val result = n.seconds.toJava assertEquals(expSecs, result.getSeconds) assertEquals(expNanos, result.getNano) } @@ -87,19 +88,12 @@ class DurationConvertersTest { @Test def javaNanosPartToScalaDuration(): Unit = { - Seq[Long](Long.MinValue + 1L, -1L, 0L, 1L, Long.MaxValue).foreach { n => + val nanosPerSecond = 1000000000L + Seq[Long](-nanosPerSecond - 1L, 0L, 1L, nanosPerSecond - 1L).foreach { n => assertEquals(n, toScala(JavaDuration.ofNanos(n)).toNanos) } } - @Test - def unsupportedScalaDurationThrows(): Unit = { - Seq(Duration.Inf, Duration.MinusInf, Duration.Undefined).foreach { d => - val res = Try { toJava(d) } - assertTrue(s"Expected exception for $d but got success", res.isFailure) - } - } - @Test def unsupportedJavaDurationThrows(): Unit = { Seq(JavaDuration.ofSeconds(-9223372037L), JavaDuration.ofSeconds(9223372037L)).foreach { d => From c44f93a2270ed176e08f3283f971c32e42161c8e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 1 May 2018 15:20:23 +0200 Subject: [PATCH 134/340] fix up copyrights --- src/main/scala/scala/compat/java8/DurationConverters.scala | 2 +- src/test/scala/scala/compat/java8/DurationConvertersTest.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala index 55a3720..8cdd688 100644 --- a/src/main/scala/scala/compat/java8/DurationConverters.scala +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2017 Typesafe Inc. + * Copyright (C) 2012-2018 Lightbend Inc. */ package scala.compat.java8 diff --git a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala index 9ce09c1..23c2304 100644 --- a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 Lightbend Inc. + * Copyright (C) 2009-2018 Lightbend Inc. */ package scala.compat.java8 From 940ef393ce37280857be5cdea8732c8e642679f7 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 3 May 2018 11:06:44 +0200 Subject: [PATCH 135/340] drop 2.13 from the cross-build temporarily references #97 --- build.sbt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4dbf529..8fc7179 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,9 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := { - val versions = List("2.12.4", "2.11.12", "2.13.0-M3").map(_ -> true) + // no 2.13 for now in cross-build because of + // https://github.com/scala/scala-java8-compat/issues/97 + val versions = List("2.12.4", "2.11.12").map(_ -> true) Map(8 -> versions, 9 -> versions, 10 -> versions) } From 96becf38e8c75e25509f9a11ac4f79bef402061c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 3 May 2018 11:10:28 +0200 Subject: [PATCH 136/340] bump version number --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 8fc7179..725b9f2 100644 --- a/build.sbt +++ b/build.sbt @@ -26,7 +26,7 @@ def osgiExport(scalaVersion: String, version: String) = { lazy val commonSettings = Seq( organization := "org.scala-lang.modules", - version := "0.9.0-SNAPSHOT", + version := "0.9.1-SNAPSHOT", scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") ) From 7e4c4bb7e26e699ffa3e0440e4d80845628e7eb9 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 3 May 2018 11:12:31 +0200 Subject: [PATCH 137/340] drop broken Travis-CI badge from readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index acd7d53..4f89b6d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) +## scala-java8-compat [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) A Java 8 compatibility kit for Scala. From 84edd3ce2bd0b37ef84dfd58488a64f2d37c097f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 3 May 2018 11:25:29 +0200 Subject: [PATCH 138/340] add myself to Travis-CI notifications --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1baf295..2ca42a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,3 +15,4 @@ jdk: notifications: email: - jason.zaugg@lightbend.com + - seth.tisue@lightbend.com From 36974288f63da33d401cbb853acb18f1ba8956c8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 3 May 2018 11:26:34 +0200 Subject: [PATCH 139/340] fix doc syntax --- src/main/scala/scala/compat/java8/DurationConverters.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala index 8cdd688..27f3c46 100644 --- a/src/main/scala/scala/compat/java8/DurationConverters.scala +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -64,14 +64,14 @@ object DurationConverters { implicit final class DurationOps(val duration: java.time.Duration) extends AnyVal { /** - * See [[DurationConverters.toScala]] + * See [[DurationConverters#toScala]] */ def toScala: scala.concurrent.duration.FiniteDuration = DurationConverters.toScala(duration) } implicit final class FiniteDurationops(val duration: scala.concurrent.duration.FiniteDuration) extends AnyVal { /** - * See [[DurationConverters.toJava]] + * See [[DurationConverters#toJava]] */ def toJava: java.time.Duration = DurationConverters.toJava(duration) } From 1ed78ccc7ab522ba8f7e7f32a8504d11a4796dfb Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 21 May 2018 14:25:19 -0700 Subject: [PATCH 140/340] Scala 2.12.6 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 725b9f2..ceb1f08 100644 --- a/build.sbt +++ b/build.sbt @@ -3,7 +3,7 @@ import ScalaModulePlugin._ scalaVersionsByJvm in ThisBuild := { // no 2.13 for now in cross-build because of // https://github.com/scala/scala-java8-compat/issues/97 - val versions = List("2.12.4", "2.11.12").map(_ -> true) + val versions = List("2.12.6", "2.11.12").map(_ -> true) Map(8 -> versions, 9 -> versions, 10 -> versions) } From 691280577b40383c5213c0cd6fa109201b7da834 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 5 Jun 2018 12:30:28 +0900 Subject: [PATCH 141/340] fix procedure syntax --- benchmark/src/main/scala/bench/CodeGen.scala | 6 +- .../src/main/scala/bench/ParseJmhLog.scala | 2 +- fnGen/WrapFnGen.scala | 4 +- .../java8/PrimitiveIteratorConversions.scala | 18 +-- .../scala/compat/java8/StreamConverters.scala | 8 +- .../java8/collectionImpl/Accumulator.scala | 8 +- .../collectionImpl/DoubleAccumulator.scala | 10 +- .../java8/collectionImpl/IntAccumulator.scala | 10 +- .../collectionImpl/LongAccumulator.scala | 10 +- .../compat/java8/collectionImpl/Stepper.scala | 38 +++--- .../java8/converterImpl/StepsVector.scala | 4 +- .../compat/java8/OptionConvertersTest.scala | 12 +- .../scala/compat/java8/SpecializedTest.scala | 2 +- .../compat/java8/FunctionConvertersTest.scala | 112 +++++++++--------- .../compat/java8/StepConvertersTest.scala | 24 ++-- .../scala/compat/java8/StepperTest.scala | 46 +++---- .../compat/java8/StreamConvertersTest.scala | 16 +-- 17 files changed, 165 insertions(+), 165 deletions(-) diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 09a1af3..58976f6 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -38,7 +38,7 @@ object Generator { def sayArrayI(oa: Option[Array[Int]]) = oa match { case Some(a) => a.mkString("Array(", ",", ")"); case _ => "" } - def agreement(target: java.io.File, sizes: Option[Array[Int]] = None) { + def agreement(target: java.io.File, sizes: Option[Array[Int]] = None): Unit = { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => @@ -102,7 +102,7 @@ object Generator { } } - def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]] = None) { + def quickBenchWithThyme(target: java.io.File, sizes: Option[Array[Int]] = None): Unit = { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => @@ -179,7 +179,7 @@ object Generator { } } - def jmhBench(target: java.io.File = new java.io.File("JmhBench.scala"), sizes: Option[Array[Int]] = Some(jmhsizes)) { + def jmhBench(target: java.io.File = new java.io.File("JmhBench.scala"), sizes: Option[Array[Int]] = Some(jmhsizes)): Unit = { val q = "\"" if (target.exists) throw new java.io.IOException("Generator will not write to existing file: " + target.getPath) writeTo(target){ pr => diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala index 32d110a..90cc9d3 100644 --- a/benchmark/src/main/scala/bench/ParseJmhLog.scala +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -63,7 +63,7 @@ object ParseJmhLog { "mdtc" -> "map/filter/take trio" ) - private def ensure(satisfied: Boolean)(not: => Unit) { + private def ensure(satisfied: Boolean)(not: => Unit): Unit = { if (!satisfied) { not assert(satisfied) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 46d79f3..5a953cb 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -291,7 +291,7 @@ object WrapFnGen { lines.iterator.filter(_.nonBlank) == text.lines.filter(_.nonBlank) } - def write(f: java.io.File, text: String) { + def write(f: java.io.File, text: String): Unit = { if (!f.exists || !sameText(f, text)) { val p = new java.io.PrintWriter(f) try { p.println(text) } @@ -299,7 +299,7 @@ object WrapFnGen { } } - def main(args: Array[String]) { + def main(args: Array[String]): Unit = { val names = args.iterator.map(x => new java.io.File(x)) write(names.next, converterContents) } diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 9210010..f5a7a44 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -42,11 +42,11 @@ object PrimitiveIteratorConverters { def hasNext = it.hasNext override def next() = it.next().asInstanceOf[java.lang.Double] def nextDouble() = it.next() - override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { while (it.hasNext) c.accept(it.next) } - override def forEachRemaining(c: java.util.function.DoubleConsumer) { + override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { while (it.hasNext) c.accept(it.next) } } @@ -63,11 +63,11 @@ object PrimitiveIteratorConverters { def hasNext = it.hasNext override def next() = it.next().asInstanceOf[java.lang.Integer] def nextInt() = it.next() - override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { while (it.hasNext) c.accept(it.next) } - override def forEachRemaining(c: java.util.function.IntConsumer) { + override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { while (it.hasNext) c.accept(it.next) } } @@ -84,11 +84,11 @@ object PrimitiveIteratorConverters { def hasNext = it.hasNext override def next() = it.next().asInstanceOf[java.lang.Long] def nextLong() = it.next() - override def remove() { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { while (it.hasNext) c.accept(it.next) } - override def forEachRemaining(c: java.util.function.LongConsumer) { + override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { while (it.hasNext) c.accept(it.next) } } diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 80f7077..4f773a9 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -96,7 +96,7 @@ trait Priority1StreamConverters extends Priority2StreamConverters { if (stream.isParallel) accumulate.to[Coll](cbf) else { val b = cbf() - stream.forEachOrdered(new java.util.function.Consumer[A]{ def accept(a: A) { b += a } }) + stream.forEachOrdered(new java.util.function.Consumer[A]{ def accept(a: A): Unit = { b += a } }) b.result() } } @@ -268,7 +268,7 @@ with converterImpl.Priority1AccumulatorConverters if (stream.isParallel) accumulate.to[Coll](cbf) else { val b = cbf() - stream.forEachOrdered(new java.util.function.DoubleConsumer{ def accept(d: Double) { b += d } }) + stream.forEachOrdered(new java.util.function.DoubleConsumer{ def accept(d: Double): Unit = { b += d } }) b.result() } } @@ -281,7 +281,7 @@ with converterImpl.Priority1AccumulatorConverters if (stream.isParallel) accumulate.to[Coll](cbf) else { val b = cbf() - stream.forEachOrdered(new java.util.function.IntConsumer{ def accept(d: Int) { b += d } }) + stream.forEachOrdered(new java.util.function.IntConsumer{ def accept(d: Int): Unit = { b += d } }) b.result() } } @@ -294,7 +294,7 @@ with converterImpl.Priority1AccumulatorConverters if (stream.isParallel) accumulate.to[Coll](cbf) else { val b = cbf() - stream.forEachOrdered(new java.util.function.LongConsumer{ def accept(d: Long) { b += d } }) + stream.forEachOrdered(new java.util.function.LongConsumer{ def accept(d: Long): Unit = { b += d } }) b.result() } } diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala index 4f1eeb8..39f68ac 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -212,10 +212,10 @@ object Accumulator { def supplier[A] = new java.util.function.Supplier[Accumulator[A]]{ def get: Accumulator[A] = new Accumulator[A] } /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def adder[A] = new java.util.function.BiConsumer[Accumulator[A], A]{ def accept(ac: Accumulator[A], a: A) { ac += a } } + def adder[A] = new java.util.function.BiConsumer[Accumulator[A], A]{ def accept(ac: Accumulator[A], a: A): Unit = { ac += a } } /** A `BiConsumer` that merges `Accumulator`s, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]) { a1 drain a2 } } + def merger[A] = new java.util.function.BiConsumer[Accumulator[A], Accumulator[A]]{ def accept(a1: Accumulator[A], a2: Accumulator[A]): Unit = { a1 drain a2 } } /** Builds an `Accumulator` from any `TraversableOnce` */ def from[A](source: TraversableOnce[A]) = { @@ -290,7 +290,7 @@ private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) exte } // Overridden for efficiency - override def foreach(f: A => Unit) { + override def foreach(f: A => Unit): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i @@ -304,7 +304,7 @@ private[java8] class AccumulatorStepper[A](private val acc: Accumulator[A]) exte } // Overridden for efficiency - override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index 65fabe6..d43e40d 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -206,13 +206,13 @@ object DoubleAccumulator { def supplier = new java.util.function.Supplier[DoubleAccumulator]{ def get: DoubleAccumulator = new DoubleAccumulator } /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. */ - def adder = new java.util.function.ObjDoubleConsumer[DoubleAccumulator]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + def adder = new java.util.function.ObjDoubleConsumer[DoubleAccumulator]{ def accept(ac: DoubleAccumulator, a: Double): Unit = { ac += a } } /** A `BiConsumer` that adds a boxed `Double` to an `DoubleAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[DoubleAccumulator, Double]{ def accept(ac: DoubleAccumulator, a: Double) { ac += a } } + def boxedAdder = new java.util.function.BiConsumer[DoubleAccumulator, Double]{ def accept(ac: DoubleAccumulator, a: Double): Unit = { ac += a } } /** A `BiConsumer` that merges `DoubleAccumulator`s, suitable for use with `java.util.stream.DoubleStream`'s `collect` method. Suitable for `Stream[Double]` also. */ - def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator) { a1 drain a2 } } + def merger = new java.util.function.BiConsumer[DoubleAccumulator, DoubleAccumulator]{ def accept(a1: DoubleAccumulator, a2: DoubleAccumulator): Unit = { a1 drain a2 } } /** Builds a `DoubleAccumulator` from any `Double`-valued `TraversableOnce` */ def from[A](source: TraversableOnce[Double]) = { @@ -287,7 +287,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator } // Overridden for efficiency - override def foreach(f: Double => Unit) { + override def foreach(f: Double => Unit): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i @@ -301,7 +301,7 @@ private[java8] class DoubleAccumulatorStepper(private val acc: DoubleAccumulator } // Overridden for efficiency - override def forEachRemaining(f: java.util.function.DoubleConsumer) { + override def forEachRemaining(f: java.util.function.DoubleConsumer): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index 129ed9b..d962d24 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -213,13 +213,13 @@ object IntAccumulator { def supplier = new java.util.function.Supplier[IntAccumulator]{ def get: IntAccumulator = new IntAccumulator } /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.IntStream`'s `collect` method. */ - def adder = new java.util.function.ObjIntConsumer[IntAccumulator]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + def adder = new java.util.function.ObjIntConsumer[IntAccumulator]{ def accept(ac: IntAccumulator, a: Int): Unit = { ac += a } } /** A `BiConsumer` that adds a boxed `Int` to an `IntAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[IntAccumulator, Int]{ def accept(ac: IntAccumulator, a: Int) { ac += a } } + def boxedAdder = new java.util.function.BiConsumer[IntAccumulator, Int]{ def accept(ac: IntAccumulator, a: Int): Unit = { ac += a } } /** A `BiConsumer` that merges `IntAccumulator`s, suitable for use with `java.util.stream.IntStream`'s `collect` method. Suitable for `Stream[Int]` also. */ - def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator) { a1 drain a2 } } + def merger = new java.util.function.BiConsumer[IntAccumulator, IntAccumulator]{ def accept(a1: IntAccumulator, a2: IntAccumulator): Unit = { a1 drain a2 } } /** Builds an `IntAccumulator` from any `Int`-valued `TraversableOnce` */ def from[A](source: TraversableOnce[Int]) = { @@ -294,7 +294,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte } // Overridden for efficiency - override def foreach(f: Int => Unit) { + override def foreach(f: Int => Unit): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i @@ -308,7 +308,7 @@ private[java8] class IntAccumulatorStepper(private val acc: IntAccumulator) exte } // Overridden for efficiency - override def forEachRemaining(f: java.util.function.IntConsumer) { + override def forEachRemaining(f: java.util.function.IntConsumer): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 1c4bdd3..06faa21 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -207,13 +207,13 @@ object LongAccumulator { def supplier = new java.util.function.Supplier[LongAccumulator]{ def get: LongAccumulator = new LongAccumulator } /** A `BiConsumer` that adds an element to an `Accumulator`, suitable for use with `java.util.stream.LongStream`'s `collect` method. */ - def adder = new java.util.function.ObjLongConsumer[LongAccumulator]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + def adder = new java.util.function.ObjLongConsumer[LongAccumulator]{ def accept(ac: LongAccumulator, a: Long): Unit = { ac += a } } /** A `BiConsumer` that adds a boxed `Long` to an `LongAccumulator`, suitable for use with `java.util.stream.Stream`'s `collect` method. */ - def boxedAdder = new java.util.function.BiConsumer[LongAccumulator, Long]{ def accept(ac: LongAccumulator, a: Long) { ac += a } } + def boxedAdder = new java.util.function.BiConsumer[LongAccumulator, Long]{ def accept(ac: LongAccumulator, a: Long): Unit = { ac += a } } /** A `BiConsumer` that merges `LongAccumulator`s, suitable for use with `java.util.stream.LongStream`'s `collect` method. Suitable for `Stream[Long]` also. */ - def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator) { a1 drain a2 } } + def merger = new java.util.function.BiConsumer[LongAccumulator, LongAccumulator]{ def accept(a1: LongAccumulator, a2: LongAccumulator): Unit = { a1 drain a2 } } /** Builds a `LongAccumulator` from any `Long`-valued `TraversableOnce` */ def from[A](source: TraversableOnce[Long]) = { @@ -288,7 +288,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex } // Overridden for efficiency - override def foreach(f: Long => Unit) { + override def foreach(f: Long => Unit): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i @@ -302,7 +302,7 @@ private[java8] class LongAccumulatorStepper(private val acc: LongAccumulator) ex } // Overridden for efficiency - override def forEachRemaining(f: java.util.function.LongConsumer) { + override def forEachRemaining(f: java.util.function.LongConsumer): Unit = { while (N > 0) { if (i >= n) loadMore() val i0 = i diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index a78d1f5..ffc94cb 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -139,7 +139,7 @@ trait StepperLike[@specialized(Double, Int, Long) A, +CC] { self: CC => /** Applies `f` to every remaining element in the collection. * This is a terminal operation. */ - def foreach(f: A => Unit) { while (hasStep) f(nextStep) } + def foreach(f: A => Unit): Unit = { while (hasStep) f(nextStep) } /** Repeatedly merges elements with `op` until only a single element remains. * Throws an exception if the `Stepper` is empty. @@ -215,21 +215,21 @@ trait TryStepper[@specialized(Double, Int, Long) A] extends Stepper[A] with Step protected def knownUncachedSize: Long final def tryStep(f: A => Unit): Boolean = if (myCacheIsFull) { f(myCache); myCacheIsFull = false; true } else tryUncached(f) protected def tryUncached(f: A => Unit): Boolean - final override def foreach(f: A => Unit) { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } - protected def foreachUncached(f: A => Unit) { while (tryUncached(f)) {} } + final override def foreach(f: A => Unit): Unit = { if (myCacheIsFull) { f(myCache); myCacheIsFull = false }; foreachUncached(f) } + protected def foreachUncached(f: A => Unit): Unit = { while (tryUncached(f)) {} } def spliterator: Spliterator[A] = new ProxySpliteratorViaTry[A](this) } private[collectionImpl] class ProxySpliteratorViaTry[A](underlying: TryStepper[A]) extends Spliterator[A] { def characteristics() = underlying.characteristics def estimateSize() = underlying.knownSize def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryStep(a => f.accept(a)) - override def forEachRemaining(f: java.util.function.Consumer[_ >: A]) { underlying.foreach(a => f.accept(a)) } + override def forEachRemaining(f: java.util.function.Consumer[_ >: A]): Unit = { underlying.foreach(a => f.accept(a)) } def trySplit() = underlying.substep() match { case null => null; case x => new ProxySpliteratorViaTry[A](x) } } /** Any `AnyStepper` combines the functionality of a Java `Iterator`, a Java `Spliterator`, and a `Stepper`. */ trait AnyStepper[A] extends Stepper[A] with java.util.Iterator[A] with Spliterator[A] with StepperLike[A, AnyStepper[A]] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { while (hasNext) { c.accept(next) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: A]): Unit = { while (hasNext) { c.accept(next) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = next @@ -269,8 +269,8 @@ private[collectionImpl] object AnyStepper { /** A `DoubleStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Double` values. */ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfDouble with Spliterator.OfDouble with StepperLike[Double, DoubleStepper] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]) { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } - override def forEachRemaining(c: java.util.function.DoubleConsumer) { while (hasNext) { c.accept(nextDouble) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { while (hasNext) { c.accept(java.lang.Double.valueOf(nextDouble)) } } + override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { while (hasNext) { c.accept(nextDouble) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextDouble @@ -285,8 +285,8 @@ trait DoubleStepper extends Stepper[Double] with java.util.PrimitiveIterator.OfD /** An `IntStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Int` values. */ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt with Spliterator.OfInt with StepperLike[Int, IntStepper] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]) { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } - override def forEachRemaining(c: java.util.function.IntConsumer) { while (hasNext) { c.accept(nextInt) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { while (hasNext) { c.accept(java.lang.Integer.valueOf(nextInt)) } } + override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { while (hasNext) { c.accept(nextInt) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextInt @@ -301,8 +301,8 @@ trait IntStepper extends Stepper[Int] with java.util.PrimitiveIterator.OfInt wit /** A `LongStepper` combines the functionality of a Java `PrimitiveIterator`, a Java `Spliterator`, and a `Stepper`, all specialized for `Long` values. */ trait LongStepper extends Stepper[Long] with java.util.PrimitiveIterator.OfLong with Spliterator.OfLong with StepperLike[Long, LongStepper] { - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]) { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } - override def forEachRemaining(c: java.util.function.LongConsumer) { while (hasNext) { c.accept(nextLong) } } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { while (hasNext) { c.accept(java.lang.Long.valueOf(nextLong)) } } + override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { while (hasNext) { c.accept(nextLong) } } def hasStep = hasNext() def knownSize = getExactSizeIfKnown def nextStep = nextLong @@ -342,7 +342,7 @@ object Stepper { extends AnyStepper[A] with java.util.function.Consumer[A] { private var cache: A = null.asInstanceOf[A] private var cached: Boolean = false - def accept(a: A) { cache = a; cached = true } + def accept(a: A): Unit = { cache = a; cached = true } private def loadCache: Boolean = sp.tryAdvance(this) private def useCache(c: java.util.function.Consumer[_ >: A]): Boolean = { @@ -361,7 +361,7 @@ object Stepper { if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 else sz } - override def forEachRemaining(c: java.util.function.Consumer[_ >: A]) { + override def forEachRemaining(c: java.util.function.Consumer[_ >: A]): Unit = { useCache(c) sp.forEachRemaining(c) } @@ -394,7 +394,7 @@ object Stepper { extends DoubleStepper with java.util.function.DoubleConsumer { private var cache: Double = Double.NaN private var cached: Boolean = false - def accept(d: Double) { cache = d; cached = true } + def accept(d: Double): Unit = { cache = d; cached = true } private def loadCache: Boolean = sp.tryAdvance(this) private def useCache(c: java.util.function.DoubleConsumer): Boolean = { @@ -412,7 +412,7 @@ object Stepper { if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 else sz } - override def forEachRemaining(c: java.util.function.DoubleConsumer) { + override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { useCache(c) sp.forEachRemaining(c) } @@ -443,7 +443,7 @@ object Stepper { extends IntStepper with java.util.function.IntConsumer { private var cache: Int = 0 private var cached: Boolean = false - def accept(i: Int) { cache = i; cached = true } + def accept(i: Int): Unit = { cache = i; cached = true } private def loadCache: Boolean = sp.tryAdvance(this) private def useCache(c: java.util.function.IntConsumer): Boolean = { @@ -461,7 +461,7 @@ object Stepper { if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 else sz } - override def forEachRemaining(c: java.util.function.IntConsumer) { + override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { useCache(c) sp.forEachRemaining(c) } @@ -492,7 +492,7 @@ object Stepper { extends LongStepper with java.util.function.LongConsumer { private var cache: Long = 0L private var cached: Boolean = false - def accept(l: Long) { cache = l; cached = true } + def accept(l: Long): Unit = { cache = l; cached = true } private def loadCache: Boolean = sp.tryAdvance(this) private def useCache(c: java.util.function.LongConsumer): Boolean = { @@ -510,7 +510,7 @@ object Stepper { if (cached && sz < Long.MaxValue && sz >= 0) sz + 1 else sz } - override def forEachRemaining(c: java.util.function.LongConsumer) { + override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { useCache(c) sp.forEachRemaining(c) } diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index efbaa2d..b0abe26 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -17,7 +17,7 @@ private[java8] trait StepsVectorLike[A] { protected var data: Array[AnyRef] = null protected var index1: Int = 32 protected var data1: Array[AnyRef] = null - protected final def advanceData(iX: Int) { + protected final def advanceData(iX: Int): Unit = { index1 += 1 if (index >= 32) initTo(iX) else { @@ -25,7 +25,7 @@ private[java8] trait StepsVectorLike[A] { index = 0 } } - protected final def initTo(iX: Int) { + protected final def initTo(iX: Int): Unit = { myVector.length match { case x if x <= 0x20 => index = iX diff --git a/src/test/java/scala/compat/java8/OptionConvertersTest.scala b/src/test/java/scala/compat/java8/OptionConvertersTest.scala index 4c21bb5..a93b494 100644 --- a/src/test/java/scala/compat/java8/OptionConvertersTest.scala +++ b/src/test/java/scala/compat/java8/OptionConvertersTest.scala @@ -11,7 +11,7 @@ class OptionConvertersTest { import OptionConverters._ @Test - def scalaToEverything() { + def scalaToEverything(): Unit = { val o = Option("fish") val n = (None: Option[String]) val od = Option(2.7) @@ -37,7 +37,7 @@ class OptionConvertersTest { } @Test - def javaGenericToEverything() { + def javaGenericToEverything(): Unit = { val o = Optional.of("fish") val n = Optional.empty[String] val od = Optional.of(2.7) @@ -63,7 +63,7 @@ class OptionConvertersTest { } @Test - def javaOptionalDoubleToEverything() { + def javaOptionalDoubleToEverything(): Unit = { val o = OptionalDouble.of(2.7) val n = OptionalDouble.empty assertEquals(o.asScala, Option(o.getAsDouble)) @@ -73,7 +73,7 @@ class OptionConvertersTest { } @Test - def javaOptionalIntToEverything() { + def javaOptionalIntToEverything(): Unit = { val o = OptionalInt.of(4) val n = OptionalInt.empty assertEquals(o.asScala, Option(o.getAsInt)) @@ -83,7 +83,7 @@ class OptionConvertersTest { } @Test - def javaOptionalLongToEverything() { + def javaOptionalLongToEverything(): Unit = { val o = OptionalLong.of(-1) val n = OptionalLong.empty assertEquals(o.asScala, Option(o.getAsLong)) @@ -93,7 +93,7 @@ class OptionConvertersTest { } @Test - def nonExtensionConversions() { + def nonExtensionConversions(): Unit = { assertEquals(toScala(Optional.of("fish")), Option("fish")) assertEquals(toScala(Optional.empty[String]), None) assertEquals(toJava(Option("fish")), Optional.of("fish")) diff --git a/src/test/java/scala/compat/java8/SpecializedTest.scala b/src/test/java/scala/compat/java8/SpecializedTest.scala index cc7f2f4..7bd4a80 100644 --- a/src/test/java/scala/compat/java8/SpecializedTest.scala +++ b/src/test/java/scala/compat/java8/SpecializedTest.scala @@ -7,7 +7,7 @@ import org.junit.Test import SpecializedTestSupport.IntIdentity class SpecializedTest { - @Test def specializationWorks() { + @Test def specializationWorks(): Unit = { val intIdentity: (Int => Int) = new IntIdentity().asInstanceOf[Int => Int] intIdentity(24) // this function checks that it was called via the specialized apply variant. } diff --git a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala index d226ec6..77881dd 100644 --- a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala @@ -28,9 +28,9 @@ class FunctionConvertersTest { // BiConsumer tests; conceptually widens to BiFunction, narrows to ObjLongConsumer @Test - def test_BiConsumer() { - val bic1 = new BiConsumer[String, File]{ def accept(s: String, f: File) { save((s,f)) } } - val bic2 = new BiConsumer[Int, Long]{ def accept(i: Int, l: Long) { save((i,l)) } } + def test_BiConsumer(): Unit = { + val bic1 = new BiConsumer[String, File]{ def accept(s: String, f: File): Unit = { save((s,f)) } } + val bic2 = new BiConsumer[Int, Long]{ def accept(i: Int, l: Long): Unit = { save((i,l)) } } val sbic = (s: String, f: File) => { save((s,f)); () } val zbic = (i: Int, l: Long) => { save((i,l)); () } def jbic[A, B](bic: BiConsumer[A, B])(a: A, b: B) = { bic.accept(a,b); recall == ((a,b)) } @@ -48,7 +48,7 @@ class FunctionConvertersTest { // BiFunction tests; conceptually narrows to any of the Bi functions or to ObjLongConsumer etc @Test - def test_BiFunction() { + def test_BiFunction(): Unit = { val bif1 = new BiFunction[String, File, (String, File)]{ def apply(s: String, f: File) = (s,f) } val bif2 = new BiFunction[Int, Long, Double]{ def apply(i: Int, l: Long) = i.toDouble*l } val sbif = (s: String, f: File) => (s,f) @@ -67,7 +67,7 @@ class FunctionConvertersTest { // BinaryOperator tests; actually widens to BiFunction and conceptually narrows to IntBinaryOperator etc. @Test - def test_BinaryOperator() { + def test_BinaryOperator(): Unit = { val bop1 = new BinaryOperator[String]{ def apply(s: String, t: String) = s + t } val bop2 = new BinaryOperator[Int]{ def apply(i: Int, j: Int) = i + j } val sbop = (s: String, t: String) => s + t @@ -86,7 +86,7 @@ class FunctionConvertersTest { // BiPredicate tests; conceptually widens to BiFunction. Does not narrow (no IntBiPredicate or the like). @Test - def test_BiPredicate() { + def test_BiPredicate(): Unit = { val bip1 = new BiPredicate[String, File]{ def test(s: String, f: File) = s == f.getName } val bip2 = new BiPredicate[Int, Long]{ def test(i: Int, l: Long) = i == l } val sbip = (s: String, f: File) => s == f.getName @@ -105,7 +105,7 @@ class FunctionConvertersTest { // BooleanSupplier tests; conceptually widens to Supplier and Function. @Test - def test_BooleanSupplier() { + def test_BooleanSupplier(): Unit = { val bsup = new BooleanSupplier{ def getAsBoolean = true } val sbup = () => true def foo(bs: BooleanSupplier) = bs.getAsBoolean @@ -119,9 +119,9 @@ class FunctionConvertersTest { // Consumer tests; conceptually widens to Function and narrows to IntConsumer etc. @Test - def test_Consumer() { - val con1 = new Consumer[String]{ def accept(s: String) { save(s) } } - val con2 = new Consumer[Int]{ def accept(i: Int) { save(i) } } + def test_Consumer(): Unit = { + val con1 = new Consumer[String]{ def accept(s: String): Unit = { save(s) } } + val con2 = new Consumer[Int]{ def accept(i: Int): Unit = { save(i) } } val scon = (s: String) => { save(s); () } val zcon = (i: Int) => { save(i); () } def jcon[A](c: Consumer[A])(a: A) = { c.accept(a); recall == a } @@ -138,7 +138,7 @@ class FunctionConvertersTest { // DoubleBinaryOperator tests; conceptually widens to BinaryOperator, ToDoubleBiFunction, and BiFunction @Test - def test_DoubleBinaryOperator() { + def test_DoubleBinaryOperator(): Unit = { val dbop = new DoubleBinaryOperator{ def applyAsDouble(a: Double, b: Double) = a*b } val sdbo = (a: Double, b: Double) => a*b def foo(dbo: DoubleBinaryOperator)(a: Double, b: Double) = dbo.applyAsDouble(a,b) @@ -152,8 +152,8 @@ class FunctionConvertersTest { // DoubleConsumer tests; conceptually widens to Consumer and Function @Test - def test_DoubleConsumer() { - val dcon = new DoubleConsumer{ def accept(value: Double) { save(value) } } + def test_DoubleConsumer(): Unit = { + val dcon = new DoubleConsumer{ def accept(value: Double): Unit = { save(value) } } val sdco = (d: Double) => { save(d); () } def jf(dc: DoubleConsumer)(d: Double) = { dc.accept(d); recall == d } def sf(f: Double => Unit)(d: Double) = { f(d); recall == d } @@ -165,7 +165,7 @@ class FunctionConvertersTest { // DoubleFunction tests; conceptually widens to Function, narrows to DoubleUnaryOperator and DoubleToIntFunction etc. @Test - def test_DoubleFunction() { + def test_DoubleFunction(): Unit = { val dfn1 = new DoubleFunction[String]{ def apply(value: Double) = f"$value%.3f" } val dfn2 = new DoubleFunction[Int]{ def apply(value: Double) = math.ceil(value).toInt } val sdfn = (d: Double) => f"$d%.3f" @@ -184,7 +184,7 @@ class FunctionConvertersTest { // DoublePredicate tests; conceptually widens to DoubleFunction, Predicate, and Function @Test - def test_DoublePredicate() { + def test_DoublePredicate(): Unit = { val dprd = new DoublePredicate{ def test(value: Double) = value > 0 } val sdpr = (d: Double) => d > 0 def foo(dp: DoublePredicate)(d: Double) = dp.test(d) @@ -198,7 +198,7 @@ class FunctionConvertersTest { // DoubleSupplier tests; conceptually widens to Supplier and Function @Test - def test_DoubleSupplier() { + def test_DoubleSupplier(): Unit = { val dsup = new DoubleSupplier{ def getAsDouble = 22.0/7 } val sdsu = () => 22.0/7 def foo(ds: DoubleSupplier) = ds.getAsDouble @@ -212,7 +212,7 @@ class FunctionConvertersTest { // DoubleToIntFunction tests; conceptually widens to DoubleFunction and Function @Test - def test_DoubleToIntFunction() { + def test_DoubleToIntFunction(): Unit = { val d2if = new DoubleToIntFunction{ def applyAsInt(value: Double) = math.ceil(value).toInt } val sd2i = (d: Double) => math.ceil(d).toInt def foo(di: DoubleToIntFunction)(d: Double) = di.applyAsInt(d) @@ -226,7 +226,7 @@ class FunctionConvertersTest { // DoubleToLongFunction tests; conceptually widens to DoubleFunction and Function @Test - def test_DoubleToLongFunction() { + def test_DoubleToLongFunction(): Unit = { val d2lf = new DoubleToLongFunction{ def applyAsLong(value: Double) = java.lang.Double.doubleToRawLongBits(value) } val sd2l = (d: Double) => java.lang.Double.doubleToRawLongBits(d) def foo(dl: DoubleToLongFunction)(d: Double) = dl.applyAsLong(d) @@ -240,7 +240,7 @@ class FunctionConvertersTest { // DoubleUnaryOperator tests; conceptually widens to DoubleFunction and ToDoubleFunction and Function @Test - def test_DoubleUnaryOperator() { + def test_DoubleUnaryOperator(): Unit = { val duop = new DoubleUnaryOperator{ def applyAsDouble(value: Double) = 1.0 - value } val sduo = (d: Double) => 1.0 - d def foo(du: DoubleUnaryOperator)(d: Double) = du.applyAsDouble(d) @@ -254,7 +254,7 @@ class FunctionConvertersTest { // Function tests; conceptually narrows to everything except BiFunction and its conceptual subclasses @Test - def test_Function() { + def test_Function(): Unit = { val fun1 = new Function[String, File]{ def apply(s: String): File = new File(s) } val fun2 = new Function[Int, Long]{ def apply(i: Int): Long = ((i.toLong)<<32) | i } def sfun = (s: String) => new File(s) @@ -283,7 +283,7 @@ class FunctionConvertersTest { // IntBinaryOperator tests; conceptually widens to BinaryOperator, ToIntBiFunction, and BiFunction @Test - def test_IntBinaryOperator() { + def test_IntBinaryOperator(): Unit = { val ibop = new IntBinaryOperator{ def applyAsInt(a: Int, b: Int) = a ^ b } val sibo = (i: Int, j: Int) => i ^ j def foo(ibo: IntBinaryOperator)(a: Int, b: Int) = ibo.applyAsInt(a,b) @@ -297,8 +297,8 @@ class FunctionConvertersTest { // IntConsumer tests; conceptually widens to Consumer and Function @Test - def test_IntConsumer() { - val icon = new IntConsumer{ def accept(i: Int) { save(i) } } + def test_IntConsumer(): Unit = { + val icon = new IntConsumer{ def accept(i: Int): Unit = { save(i) } } val sico = (i: Int) => { save(i); () } def jf(ic: IntConsumer)(d: Int) = { ic.accept(d); recall == d } def sf(f: Int => Unit)(d: Int) = { f(d); recall == d } @@ -310,7 +310,7 @@ class FunctionConvertersTest { // IntFunction tests; conceptually widens to Function @Test - def test_IntFunction() { + def test_IntFunction(): Unit = { val ifn1 = new IntFunction[String]{ def apply(i: Int) = "!"*i } val ifn2 = new IntFunction[Long]{ def apply(i: Int) = ((i.toLong) << 32) | i } val sifn = (i: Int) => "!"*i @@ -329,7 +329,7 @@ class FunctionConvertersTest { // IntPredicate tests; conceptually widens to IntFunction, Predicate, and Function @Test - def test_IntPredicate() { + def test_IntPredicate(): Unit = { val iprd = new IntPredicate{ def test(i: Int) = i < 0 } val sipr = (i: Int) => i < 0 def foo(ip: IntPredicate)(d: Int) = ip.test(d) @@ -343,7 +343,7 @@ class FunctionConvertersTest { // IntSupplier tests; conceptually widens to Supplier and Function @Test - def test_IntSupplier() { + def test_IntSupplier(): Unit = { val isup = new IntSupplier{ def getAsInt = 42 } val sisu = () => 42 def foo(ds: IntSupplier) = ds.getAsInt @@ -357,7 +357,7 @@ class FunctionConvertersTest { // IntToDoubleFunction tests; conceptually widens to ToDoubleFunction, IntFunction, and Function @Test - def test_IntToDoubleFunction() { + def test_IntToDoubleFunction(): Unit = { val i2df = new IntToDoubleFunction{ def applyAsDouble(i: Int) = i + 0.1*i } def si2d = (i: Int) => i + 0.1*i def foo(id: IntToDoubleFunction)(i: Int) = id.applyAsDouble(i) @@ -371,7 +371,7 @@ class FunctionConvertersTest { // IntToLongFunction tests; conceptually widens to ToLongFunction, IntFunction, and Function @Test - def test_IntToLongFunction() { + def test_IntToLongFunction(): Unit = { val i2lf = new IntToLongFunction { def applyAsLong(i: Int) = (i.toLong << 32) | i } val si2l = (i: Int) => (i.toLong << 32) | i def foo(il: IntToLongFunction)(d: Int) = il.applyAsLong(d) @@ -385,7 +385,7 @@ class FunctionConvertersTest { // IntUnaryOperator tests; conceptually widens to ToIntFunction, IntFunction, and Function @Test - def test_IntUnaryOperator() { + def test_IntUnaryOperator(): Unit = { val iuop = new IntUnaryOperator{ def applyAsInt(i: Int) = ~i } val siuo = (i: Int) => ~i def foo(iu: IntUnaryOperator)(d: Int) = iu.applyAsInt(d) @@ -399,7 +399,7 @@ class FunctionConvertersTest { // LongBinaryOperator tests; conceptually widens to ToLongFunction, LongFunction, and Function @Test - def test_LongBinaryOperator() { + def test_LongBinaryOperator(): Unit = { val lbop = new LongBinaryOperator{ def applyAsLong(a: Long, b: Long) = a | b } val slbo = (a: Long, b: Long) => a | b def foo(lbo: LongBinaryOperator)(a: Long, b: Long) = lbo.applyAsLong(a,b) @@ -413,8 +413,8 @@ class FunctionConvertersTest { // LongConsumer tests; conceptually widens to Consumer and Function @Test - def test_LongConsumer() { - val lcon = new LongConsumer{ def accept(l: Long) { save(l) } } + def test_LongConsumer(): Unit = { + val lcon = new LongConsumer{ def accept(l: Long): Unit = { save(l) } } val slco = (l: Long) => { save(l); () } def jf(lc: LongConsumer)(d: Long) = { lc.accept(d); recall == d } def sf(f: Long => Unit)(d: Long) = { f(d); recall == d } @@ -426,7 +426,7 @@ class FunctionConvertersTest { // LongFunction tests; conceptually widens to Function @Test - def test_LongFunction() { + def test_LongFunction(): Unit = { val lfn1 = new LongFunction[String]{ def apply(l: Long) = l.toString } val lfn2 = new LongFunction[Int]{ def apply(l: Long) = (l & 0xFFFFFF).toInt } val slfn = (l: Long) => l.toString @@ -445,7 +445,7 @@ class FunctionConvertersTest { // LongPredicate tests; conceptually widens to LongFunction and Predicate and Function @Test - def test_LongPredicate() { + def test_LongPredicate(): Unit = { val lprd = new LongPredicate{ def test(l: Long) = l < 1 } val slpr = (l: Long) => l < 1 def foo(lp: LongPredicate)(d: Long) = lp.test(d) @@ -459,7 +459,7 @@ class FunctionConvertersTest { // LongSupplier tests; conceptually widens to ToLongFunction and Supplier and Function @Test - def test_LongSupplier() { + def test_LongSupplier(): Unit = { val lsup = new LongSupplier{ def getAsLong = 1000000000000L } val slsu = () => 1000000000000L def foo(ls: LongSupplier) = ls.getAsLong @@ -473,7 +473,7 @@ class FunctionConvertersTest { // LongToDoubleFunction tests; conceptually widens to ToDoubleFunction, LongFunction, and Function @Test - def test_LongToDoubleFunction() { + def test_LongToDoubleFunction(): Unit = { val l2df = new LongToDoubleFunction{ def applyAsDouble(l: Long) = l + 1e-4*l } def sl2d = (l: Long) => l + 1e-4*l def foo(ld: LongToDoubleFunction)(l: Long) = ld.applyAsDouble(l) @@ -487,7 +487,7 @@ class FunctionConvertersTest { // LongToIntFunction tests; conceptually widens to ToIntFunction, LongFunction, and Function @Test - def test_LongToIntFunction() { + def test_LongToIntFunction(): Unit = { val l2if = new LongToIntFunction{ def applyAsInt(l :Long) = (l & 0xFFFFFF).toInt } val sl2i = (l: Long) => (l & 0xFFFFFF).toInt def foo(li: LongToIntFunction)(l: Long) = li.applyAsInt(l) @@ -501,7 +501,7 @@ class FunctionConvertersTest { // LongUnaryOperator tests; conceptually widens to LongFunction, ToLongFunction, and Function @Test - def test_LongUnaryOperator() { + def test_LongUnaryOperator(): Unit = { val luop = new LongUnaryOperator{ def applyAsLong(l: Long) = -l } val sluo = (l: Long) => -l def foo(du: LongUnaryOperator)(l: Long) = du.applyAsLong(l) @@ -515,9 +515,9 @@ class FunctionConvertersTest { // ObjDoubleConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjDoubleConsumer() { - val odc1 = new ObjDoubleConsumer[String]{ def accept(s: String, d: Double) { save((s,d)) } } - val odc2 = new ObjDoubleConsumer[Int]{ def accept(i: Int, d: Double) { save((i,d)) } } + def test_ObjDoubleConsumer(): Unit = { + val odc1 = new ObjDoubleConsumer[String]{ def accept(s: String, d: Double): Unit = { save((s,d)) } } + val odc2 = new ObjDoubleConsumer[Int]{ def accept(i: Int, d: Double): Unit = { save((i,d)) } } val sodc = (s: String, d: Double) => { save((s,d)); () } val zodc = (i: Int, d: Double) => { save((i,d)); () } def jf1(odc: ObjDoubleConsumer[String])(s: String, d: Double) = { odc.accept(s,d); recall == ((s,d)) } @@ -540,9 +540,9 @@ class FunctionConvertersTest { // ObjIntConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjIntConsumer() { - val oic1 = new ObjIntConsumer[String]{ def accept(s: String, i: Int) { save((s,i)) } } - val oic2 = new ObjIntConsumer[Int]{ def accept(j: Int, i: Int) { save((j,i)) } } + def test_ObjIntConsumer(): Unit = { + val oic1 = new ObjIntConsumer[String]{ def accept(s: String, i: Int): Unit = { save((s,i)) } } + val oic2 = new ObjIntConsumer[Int]{ def accept(j: Int, i: Int): Unit = { save((j,i)) } } val soic = (s: String, i: Int) => { save((s,i)); () } val zoic = (j: Int, i: Int) => { save((j,i)); () } def jf1(oic: ObjIntConsumer[String])(s: String, i: Int) = { oic.accept(s,i); recall == ((s,i)) } @@ -565,9 +565,9 @@ class FunctionConvertersTest { // ObjLongConsumer tests; conceptually widens to Consumer and BiFunction @Test - def test_ObjLongConsumer() { - val olc1 = new ObjLongConsumer[String]{ def accept(s: String, l: Long) { save((s,l)) } } - val olc2 = new ObjLongConsumer[Int]{ def accept(i: Int, l: Long) { save((i,l)) } } + def test_ObjLongConsumer(): Unit = { + val olc1 = new ObjLongConsumer[String]{ def accept(s: String, l: Long): Unit = { save((s,l)) } } + val olc2 = new ObjLongConsumer[Int]{ def accept(i: Int, l: Long): Unit = { save((i,l)) } } val solc = (s: String, l: Long) => { save((s,l)); () } val zolc = (i: Int, l: Long) => { save((i,l)); () } def jf1(olc: ObjLongConsumer[String])(s: String, l: Long) = { olc.accept(s,l); recall == ((s,l)) } @@ -590,7 +590,7 @@ class FunctionConvertersTest { // Predicate tests; conceptually widens to Function and narrows to IntPredicate etc. @Test - def test_Predicate() { + def test_Predicate(): Unit = { val prd1 = new Predicate[String]{ def test(s: String) = s.isEmpty } val prd2 = new Predicate[Int]{ def test(i: Int) = i < 0 } def sprd = (s: String) => s.isEmpty @@ -612,7 +612,7 @@ class FunctionConvertersTest { // Supplier tests; conceptually widens to Function and narrows to IntSupplier etc. @Test - def test_Supplier() { + def test_Supplier(): Unit = { val sup1 = new Supplier[String]{ def get = "halibut" } val sup2 = new Supplier[Int]{ def get = 17 } val ssup = () => "halibut" @@ -636,7 +636,7 @@ class FunctionConvertersTest { // ToDoubleBiFunction tests; conceptually widens to BiFunction and narrows to DoubleBinaryOperator @Test - def test_ToDoubleBiFunction() { + def test_ToDoubleBiFunction(): Unit = { { val bfd1 = new ToDoubleBiFunction[String, File]{ def applyAsDouble(s: String, f: File) = s.length.toDouble * f.getName.length } val sbfd = (s: String, f: File) => s.length.toDouble * f.getName.length @@ -666,7 +666,7 @@ class FunctionConvertersTest { // ToDoubleFunction tests; conceptually widens to Function and narrows to DoubleUnaryOperator, IntToDoubleFunction, etc. @Test - def test_ToDoubleFunction() { + def test_ToDoubleFunction(): Unit = { { val fnd1 = new ToDoubleFunction[String]{ def applyAsDouble(s: String) = s.length / (s.headOption.getOrElse(0: Char)+1).toDouble } val sfnd = (s: String) => s.length / (s.headOption.getOrElse(0: Char)+1).toDouble @@ -694,7 +694,7 @@ class FunctionConvertersTest { // ToIntBiFunction tests; conceptually widens to BiFunction and narrows to IntBinaryOperator @Test - def test_ToIntBiFunction() { + def test_ToIntBiFunction(): Unit = { { val bfi1 = new ToIntBiFunction[String, File]{ def applyAsInt(s: String, f: File) = s.length + f.getName.length } val sbfi = (s: String, f: File) => s.length.toInt + f.getName.length @@ -723,7 +723,7 @@ class FunctionConvertersTest { // ToIntFunction tests; conceptually widens to Function and narrows to IntUnaryOperator, etc.. @Test - def test_ToIntFunction() { + def test_ToIntFunction(): Unit = { { val fni1 = new ToIntFunction[String]{ def applyAsInt(s: String) = s.length } val sfni = (s: String) => s.length @@ -751,7 +751,7 @@ class FunctionConvertersTest { // ToLongBiFunction tests; conceptually widens to BiFunction and narrows to LongBinaryOperator @Test - def test_ToLongBiFunction() { + def test_ToLongBiFunction(): Unit = { { val bfl1 = new ToLongBiFunction[String, File]{ def applyAsLong(s: String, f: File) = s.length * f.getName.length } val sbfl = (s: String, f: File) => s.length.toLong * f.getName.length @@ -780,7 +780,7 @@ class FunctionConvertersTest { // ToLongFunction tests; conceptually widens to Function and narrows to LongUnaryOperator, LongToIntFunction etc.. @Test - def test_ToLongFunction() { + def test_ToLongFunction(): Unit = { { val fnl1 = new ToLongFunction[String]{ def applyAsLong(s: String) = s.length.toLong << 16 } val sfnl = (s: String) => s.length.toLong << 16 @@ -808,7 +808,7 @@ class FunctionConvertersTest { // UnaryOperator tests; actually widens to Function and conceptually narrows to IntUnaryOperator etc.. @Test - def test_UnaryOperator() { + def test_UnaryOperator(): Unit = { { val uop1 = new UnaryOperator[String]{ def apply(s: String) = s.toUpperCase } val suop = (s: String) => s.toUpperCase diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index 0add1f9..b7a43e4 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -38,45 +38,45 @@ class StepConvertersTest { } } - def _eh_[X](x: => X)(implicit correctSpec: SpecCheck) { + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) } - def IFFY[X](x: => X)(implicit correctSpec: SpecCheck) { + def IFFY[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(isAcc(x)) } - def Okay[X](x: => X)(implicit correctSpec: SpecCheck) { + def Okay[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(!isAcc(x)) assertTrue(isLin(x)) } - def Fine[X](x: => X)(implicit correctSpec: SpecCheck) { + def Fine[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(!isAcc(x)) } - def good[X](x: => X)(implicit correctSpec: SpecCheck) { + def good[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) assertTrue(!isAcc(x)) assertTrue(!isLin(x)) } - def Tell[X](x: => X)(implicit correctSpec: SpecCheck) { + def Tell[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { println(x.getClass.getName + " -> " + isAcc(x)) assertTrue(x.isInstanceOf[Stepper[_]]) correctSpec.assert(x) } @Test - def comprehensivelyGeneric() { + def comprehensivelyGeneric(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) // Collection section @@ -210,7 +210,7 @@ class StepConvertersTest { } @Test - def comprehensivelyDouble() { + def comprehensivelyDouble(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[DoubleStepper]) //Double-specific tests @@ -323,7 +323,7 @@ class StepConvertersTest { } @Test - def comprehensivelyInt() { + def comprehensivelyInt(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") // Int-specific tests @@ -446,7 +446,7 @@ class StepConvertersTest { } @Test - def shortWidening() { + def shortWidening(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( Array[Short](654321.toShort).stepper ) @@ -461,7 +461,7 @@ class StepConvertersTest { } @Test - def comprehensivelyLong() { + def comprehensivelyLong(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) // Long-specific tests @@ -584,7 +584,7 @@ class StepConvertersTest { } @Test - def comprehensivelySpecific() { + def comprehensivelySpecific(): Unit = { implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 561a980..48f3a8a 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -50,7 +50,7 @@ class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { i = sub.size0 sub } - override def forEachRemaining(f: java.util.function.IntConsumer) { while (i < size0) { f.accept(i.toInt); i += 1 } } + override def forEachRemaining(f: java.util.function.IntConsumer): Unit = { while (i < size0) { f.accept(i.toInt); i += 1 } } } class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, Int, Long) B](underlying: Stepper[A], mapping: A => B) extends Stepper[B] { @@ -59,7 +59,7 @@ class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, In def hasStep = underlying.hasStep def nextStep() = mapping(underlying.nextStep()) def tryStep(f: B => Unit): Boolean = underlying.tryStep(a => f(mapping(a))) - override def foreach(f: B => Unit) { underlying.foreach(a => f(mapping(a))) } + override def foreach(f: B => Unit): Unit = { underlying.foreach(a => f(mapping(a))) } def substep() = { val undersub = underlying.substep() if (undersub == null) null @@ -71,7 +71,7 @@ class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, In class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: A => B) extends Spliterator[B] { def characteristics = underlying.characteristics def estimateSize() = underlying.estimateSize() - def tryAdvance(f: java.util.function.Consumer[_ >: B]): Boolean = underlying.tryAdvance(new java.util.function.Consumer[A]{ def accept(a: A) { f.accept(mapping(a)) } }) + def tryAdvance(f: java.util.function.Consumer[_ >: B]): Boolean = underlying.tryAdvance(new java.util.function.Consumer[A]{ def accept(a: A): Unit = { f.accept(mapping(a)) } }) def trySplit(): Spliterator[B] = { val undersplit = underlying.trySplit() if (undersplit == null) null @@ -81,7 +81,7 @@ class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: class IntToGenericSpliterator[A](private val underlying: Spliterator.OfInt, mapping: Int => A) extends Spliterator[A] { def characteristics = underlying.characteristics def estimateSize() = underlying.estimateSize() - def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) def trySplit(): Spliterator[A] = { val undersplit = underlying.trySplit() if (undersplit == null) null @@ -91,7 +91,7 @@ class IntToGenericSpliterator[A](private val underlying: Spliterator.OfInt, mapp class IntToDoubleSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Double) extends Spliterator.OfDouble { def characteristics = underlying.characteristics def estimateSize() = underlying.estimateSize() - def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) def trySplit(): Spliterator.OfDouble = { val undersplit = underlying.trySplit() if (undersplit == null) null @@ -101,7 +101,7 @@ class IntToDoubleSpliterator(private val underlying: Spliterator.OfInt, mapping: class IntToLongSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Long) extends Spliterator.OfLong { def characteristics = underlying.characteristics def estimateSize() = underlying.estimateSize() - def tryAdvance(f: java.util.function.LongConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int) { f.accept(mapping(a)) } }) + def tryAdvance(f: java.util.function.LongConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) def trySplit(): Spliterator.OfLong = { val undersplit = underlying.trySplit() if (undersplit == null) null @@ -144,7 +144,7 @@ class StepperTest { } @Test - def stepping() { + def stepping(): Unit = { sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep == j } && !s.hasStep) } sources.foreach{ case (i, s) => val set = collection.mutable.BitSet.empty @@ -160,7 +160,7 @@ class StepperTest { } @Test - def trying() { + def trying(): Unit = { sources.foreach{ case (i,s) => val set = collection.mutable.BitSet.empty while (s.tryStep{ y => assert(!(set contains y)); set += y }) {} @@ -180,7 +180,7 @@ class StepperTest { } @Test - def substepping() { + def substepping(): Unit = { sources.foreach{ case (i,s) => val ss = s.substep assertEquals(ss == null, i < 2) @@ -196,32 +196,32 @@ class StepperTest { } @Test - def characteristically() { + def characteristically(): Unit = { val expected = Stepper.Sized | Stepper.SubSized | Stepper.Ordered sources.foreach{ case (_,s) => assertEquals(s.characteristics, expected)} sources.foreach{ case (_,s) => subs(0)(s)(x => { assertEquals(x.characteristics, expected); 0 }, _ + _) } } @Test - def knownSizes() { + def knownSizes(): Unit = { sources.foreach{ case (i,s) => assertEquals(i.toLong, s.knownSize) } sources.foreach{ case (i,s) => if (i > 0) subs(0)(s)(x => { assertEquals(x.knownSize, 1L); 0 }, _ + _) } } @Test - def count_only() { + def count_only(): Unit = { sources.foreach{ case (i, s) => assertEquals(i, s.count) } sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count.toInt, _ + _)) } } @Test - def count_conditionally() { + def count_conditionally(): Unit = { sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), s.count(_ % 3 == 0)) } sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), subs(0)(s)(_.count(_ % 3 == 0).toInt, _ + _)) } } @Test - def existence() { + def existence(): Unit = { sources.foreach{ case (i, s) => assert(i > 0 == s.exists(_ >= 0)) } sources.foreach{ case (i, s) => assert(i > 16 == s.exists(_ % 17 == 16)) } sources.foreach{ case (i, s) => assert(i > 0 == subs(false)(s)(_.exists(_ >= 0), _ || _)) } @@ -229,7 +229,7 @@ class StepperTest { } @Test - def finding() { + def finding(): Unit = { for (k <- 0 until 100) { (sources zip sources).foreach{ case ((i,s), (j,t)) => val x = util.Random.nextInt(math.min(i,j)+3) @@ -242,7 +242,7 @@ class StepperTest { } @Test - def folding() { + def folding(): Unit = { sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, s.fold("")(_ + _.toString)) } sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, subs("")(s)(_.fold("")(_ + _.toString), _ + _)) } sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, s.fold(0.0)(_ + _), 1e-10) } @@ -250,7 +250,7 @@ class StepperTest { } @Test - def foldingUntil() { + def foldingUntil(): Unit = { def expected(i: Int) = (0 until i).scan(0)(_ + _).dropWhile(_ < 6*i).headOption.getOrElse((0 until i).sum) sources.foreach{ case (i,s) => assertEquals(expected(i), s.foldTo(0)(_ + _)(_ >= 6*i)) } sources.foreach{ case (_,s) => assertEquals(-1, s.foldTo(-1)(_ * _)(_ => true)) } @@ -262,7 +262,7 @@ class StepperTest { } @Test - def foreaching() { + def foreaching(): Unit = { sources.foreach{ case (i,s) => val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] s.foreach( clq add _.toString ) @@ -276,7 +276,7 @@ class StepperTest { } @Test - def reducing() { + def reducing(): Unit = { sources.foreach{ case (i,s) => if (i==0) assertEquals(s.hasStep, false) else assertEquals((0 until i).sum, s.reduce(_ + _)) @@ -287,19 +287,19 @@ class StepperTest { } @Test - def iterating() { + def iterating(): Unit = { sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } } @Test - def spliterating() { + def spliterating(): Unit = { sources.foreach{ case (i,s) => var sum = 0 - s.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sum += i } }) + s.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sum += i } }) assertEquals(sum, (0 until i).sum) } sources.foreach{ case (i,s) => - val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int) { sm += i } }); sm }, _ + _) + val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sm += i } }); sm }, _ + _) assertEquals(sum, (0 until i).sum) } } diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index d3131a6..fbecae5 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -12,10 +12,10 @@ import scala.compat.java8.converterImpl.MakesStepper class StreamConvertersTest { - def assertEq[A](a1: A, a2: A, s: String) { assertEquals(s, a1, a2) } // Weird order normally! - def assertEq[A](a1: A, a2: A) { assertEq(a1, a2, "not equal") } - def assert(b: Boolean) { assertTrue(b) } - def assert(b: Boolean, s: String) { assertTrue(s, b) } + def assertEq[A](a1: A, a2: A, s: String): Unit = { assertEquals(s, a1, a2) } // Weird order normally! + def assertEq[A](a1: A, a2: A): Unit = { assertEq(a1, a2, "not equal") } + def assert(b: Boolean): Unit = { assertTrue(b) } + def assert(b: Boolean, s: String): Unit = { assertTrue(s, b) } def arrayO(n: Int) = (1 to n).map(_.toString).toArray def arrayD(n: Int) = (1 to n).map(_.toDouble).toArray @@ -30,7 +30,7 @@ class StreamConvertersTest { val ns = Vector(0, 1, 2, 12, 15, 16, 17, 31, 32, 33, 151, 1298, 7159) @Test - def streamAccumulate() { + def streamAccumulate(): Unit = { for (n <- ns) { val vecO = arrayO(n).toVector val accO = newStream(n).parallel.accumulate @@ -84,7 +84,7 @@ class StreamConvertersTest { } @Test - def streamToScala() { + def streamToScala(): Unit = { for (n <- ns) { val vecO = arrayO(n).toVector assertEq(vecO, newStream(n).toScala[Vector]) @@ -105,7 +105,7 @@ class StreamConvertersTest { } @Test - def streamUnbox() { + def streamUnbox(): Unit = { assert(newDoubleStream(1).boxed.unboxed.isInstanceOf[DoubleStream]) assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) @@ -131,7 +131,7 @@ class StreamConvertersTest { def hsetL(n: Int) = genhset(arrayL(n)) @Test - def scalaToStream() { + def scalaToStream(): Unit = { for (n <- ns) { val arrO = arrayO(n) val seqO = arrO.toSeq From 95aeb275f26279245cf4cd9625c06a1e6ef96a9e Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Tue, 5 Jun 2018 12:33:43 +0900 Subject: [PATCH 142/340] fix dead link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e80eb0f..93ace65 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ ## Contributing -This project has the same [guidelines for contributors](https://github.com/scala/scala/blob/master/CONTRIBUTING.md) as scala/scala. +This project has the same [guidelines for contributors](https://github.com/scala/scala/blob/2.13.x/CONTRIBUTING.md) as scala/scala. From 48039626ca865ed7bedad9108f3c8ad048db7882 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 13 Jun 2018 14:49:02 +0200 Subject: [PATCH 143/340] Simplify tag-driven releases, no longer use `scalaVersionsByJvm` This brings the scripts in line with scala-xml, scala-collection-compat, and we're doing the same for other modules --- .travis.yml | 15 ++++++++++-- admin/README.md | 33 ++++++++++++------------- admin/build.sh | 49 ++++++++++++++++---------------------- admin/publish-settings.sbt | 13 +++++----- build.sbt | 9 +++---- project/plugins.sbt | 2 +- 6 files changed, 58 insertions(+), 63 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2ca42a1..9d271a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,16 @@ language: scala + sudo: false + +jdk: + - oraclejdk8 + +scala: + # no 2.13 for now in cross-build because of + # https://github.com/scala/scala-java8-compat/issues/97 + - 2.11.12 + - 2.12.6 + env: global: # PGP_PASSPHRASE @@ -8,10 +19,10 @@ env: - secure: "lx2qFeFxh9AFmyHR7hH4Qf9flIEx8VgYj6ebzuxp1cc1ZZiXHC1256x0bHFDUH9bhJACOazOrco/+v6MBAriBkWxLBc98FrC6OkVeQMFW2ffWSBuHRclilKsQA/Lsgc81Wg+WV105hOqUNAkTXgroblInNt+KS+DhC/8FVoh9ZY=" # SONA_PASS - secure: "FZC+FZnBNeklA150vW5QDZJ5J7t+DExJrgyXWM46Wh0MobjH8cvydgC3qatItb0rDBV8l7zO1LDwl2KEi92aefw2a8E49z6qVOHgUXiI3SAx7M0UO0FFeKPmTXCLcBlbnGLcUqNjIZfuIEufQvPblKTl8qN4eMmcMn9jsNzJr28=" + script: - admin/build.sh -jdk: - - oraclejdk8 + notifications: email: - jason.zaugg@lightbend.com diff --git a/admin/README.md b/admin/README.md index 46626b4..3e9d1bf 100644 --- a/admin/README.md +++ b/admin/README.md @@ -1,11 +1,5 @@ ## Tag Driven Releasing -### Background Reading - - - http://docs.travis-ci.com/user/environment-variables/ - - http://docs.travis-ci.com/user/encryption-keys/ - - http://docs.travis-ci.com/user/encrypting-files/ - ### Initial setup for the repository To configure tag driven releases from Travis CI. @@ -13,21 +7,29 @@ To configure tag driven releases from Travis CI. 1. Generate a key pair for this repository with `./admin/genKeyPair.sh`. Edit `.travis.yml` and `admin/build.sh` as prompted. 1. Publish the public key to https://pgp.mit.edu - 1. Store other secrets as encrypted environment variables with `admin/encryptEnvVars.sh`. + 1. Store other secrets as encrypted environment variables with `./admin/encryptEnvVars.sh`. Edit `.travis.yml` as prompted. 1. Edit `.travis.yml` to use `./admin/build.sh` as the build script, and edit that script to use the tasks required for this project. - 1. Edit `build.sbt`'s `scalaVersionsByJvm in ThisBuild` to select Scala and JVM version - combinations that will be used for publishing. + Ensure that `RELEASE_COMBO` is `true` for build matrix combinations + that should be released to sonatype (when building a tag). It is important to add comments in `.travis.yml` to identify the name -of each environment variable encoded in a `:secure` section. +of each environment variable encoded in a `secure` section. After these steps, your `.travis.yml` should contain config of the form: ``` language: scala +jdk: + - openjdk6 + - oraclejdk8 + +scala: + - 2.11.12 + - 2.12.6 + env: global: # PGP_PASSPHRASE @@ -39,10 +41,6 @@ env: script: admin/build.sh -jdk: - - openjdk6 - - oraclejdk8 - notifications: email: - a@b.com @@ -62,10 +60,9 @@ without generating a new key. 1. Create a GitHub "Release" with a corresponding tag (e.g., `v0.1.1`) via the GitHub web interface. 1. The release will be published using the Scala and JVM version combinations specified - in `scalaVersionsByJvm` in `build.sbt`. - - If you need to release against a different Scala version, include the Scala version - and the JVM version to use in the tag name, separated by `#`s (e.g., `v0.1.1#2.13.0-M1#8`). - Note that the JVM version needs to be listed in `.travis.yml` for the build to run. + in the travis build matrix where `[ "$RELEASE_COMBO" = "true" ]`. + - If you need to release against a different Scala version, create a new commit that modifies + `.travis.yml` and push a new tag, e.g., `v1.2.3#2.13.0-M5`. The suffix after `#` is ignored. 1. Travis CI will schedule a build for this release. Review the build logs. 1. Log into https://oss.sonatype.org/ and identify the staging repository. 1. Sanity check its contents. diff --git a/admin/build.sh b/admin/build.sh index 7d27ba0..db8692b 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -9,45 +9,36 @@ set -e # Checking the local git clone would not work because git on travis does not fetch tags. # The version number to be published is extracted from the tag, e.g., v1.2.3 publishes -# version 1.2.3 using all Scala versions in build.sbt's `crossScalaVersions`. +# version 1.2.3 on all combinations of the travis matrix where `[ "$RELEASE_COMBO" = "true" ]`. -# When a new, binary incompatible Scala version becomes available, a previously released version -# can be released using that new Scala version by creating a new tag containing the Scala and the -# JVM version after hashes, e.g., v1.2.3#2.13.0-M1#8. The JVM version needs to be listed in -# `.travis.yml`, otherwise the required build doesn't run. +# In order to build a previously released version against a new (binary incompatible) Scala release, +# a new commit that modifies (and prunes) the Scala versions in .travis.yml needs to be added on top +# of the existing tag. Then a new tag can be created for that commit, e.g., `v1.2.3#2.13.0-M5`. +# Everything after the `#` in the tag name is ignored. + +RELEASE_COMBO=true verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" -tagPat="^v$verPat(#$verPat#[0-9]+)?$" +tagPat="^v$verPat(#.*)?$" if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then - currentJvmVer=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | sed 's/^1\.//' | sed 's/[^0-9].*//') - tagVer=$(echo $TRAVIS_TAG | sed s/#.*// | sed s/^v//) publishVersion='set every version := "'$tagVer'"' - scalaAndJvmVer=$(echo $TRAVIS_TAG | sed s/[^#]*// | sed s/^#//) - if [ "$scalaAndJvmVer" != "" ]; then - scalaVer=$(echo $scalaAndJvmVer | sed s/#.*//) - jvmVer=$(echo $scalaAndJvmVer | sed s/[^#]*// | sed s/^#//) - if [ "$jvmVer" != "$currentJvmVer" ]; then - echo "Not publishing $TRAVIS_TAG on Java version $currentJvmVer." - exit 0 - fi - publishScalaVersion='set every ScalaModulePlugin.scalaVersionsByJvm := Map('$jvmVer' -> List("'$scalaVer'" -> true))' - echo "Releasing $tagVer using Scala $scalaVer on Java version $jvmVer." - else - echo "Releasing $tagVer on Java version $currentJvmVer according to 'scalaVersionsByJvm' in build.sbt." - fi + if [ "$RELEASE_COMBO" = "true" ]; then + currentJvmVer=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | sed 's/^1\.//' | sed 's/[^0-9].*//') + echo "Releasing $tagVer with Scala $TRAVIS_SCALA_VERSION on Java version $currentJvmVer." - extraTarget="+publish-signed" - cat admin/gpg.sbt >> project/plugins.sbt - cp admin/publish-settings.sbt . + publishTask="publish-signed" - # Copied from the output of genKeyPair.sh - K=$encrypted_1ce132863fa7_key - IV=$encrypted_1ce132863fa7_iv + cat admin/gpg.sbt >> project/plugins.sbt + cp admin/publish-settings.sbt . - openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d + # Copied from the output of genKeyPair.sh + K=$encrypted_1ce132863fa7_key + IV=$encrypted_1ce132863fa7_iv + openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d + fi fi -sbt "$publishVersion" "$publishScalaVersion" clean update +test +publishLocal $extraTarget +sbt "++$TRAVIS_SCALA_VERSION" "$publishVersion" clean test publishLocal "$publishTask" diff --git a/admin/publish-settings.sbt b/admin/publish-settings.sbt index f763ea0..026c6ee 100644 --- a/admin/publish-settings.sbt +++ b/admin/publish-settings.sbt @@ -1,9 +1,8 @@ def env(key: String) = Option(System.getenv(key)).getOrElse("") -pgpPassphrase := Some(env("PGP_PASSPHRASE").toArray) - -pgpPublicRing := file("admin/pubring.asc") - -pgpSecretRing := file("admin/secring.asc") - -credentials += Credentials("Sonatype Nexus Repository Manager", "oss.sonatype.org", env("SONA_USER"), env("SONA_PASS")) +inThisBuild(Seq( + pgpPassphrase := Some(env("PGP_PASSPHRASE").toArray), + pgpPublicRing := file("admin/pubring.asc"), + pgpSecretRing := file("admin/secring.asc"), + credentials += Credentials("Sonatype Nexus Repository Manager", "oss.sonatype.org", env("SONA_USER"), env("SONA_PASS")) +)) diff --git a/build.sbt b/build.sbt index ceb1f08..fbb4c54 100644 --- a/build.sbt +++ b/build.sbt @@ -1,11 +1,8 @@ import ScalaModulePlugin._ -scalaVersionsByJvm in ThisBuild := { - // no 2.13 for now in cross-build because of - // https://github.com/scala/scala-java8-compat/issues/97 - val versions = List("2.12.6", "2.11.12").map(_ -> true) - Map(8 -> versions, 9 -> versions, 10 -> versions) -} +// no 2.13 for now in cross-build because of +// https://github.com/scala/scala-java8-compat/issues/97 +crossScalaVersions in ThisBuild := List("2.12.6", "2.11.12") val disableDocs = sys.props("nodocs") == "true" diff --git a/project/plugins.sbt b/project/plugins.sbt index 26dd0ea..d283e84 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,3 @@ scalacOptions += "-Xfatal-warnings" -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.13") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") From c6ec67a32aa5ce3f85188dae556dc26bcf4970dc Mon Sep 17 00:00:00 2001 From: Rex Kerr Date: Sat, 28 Jul 2018 15:14:41 -0700 Subject: [PATCH 144/340] Fixed NPE in VectorStepper due to dirty display vector. (Could occur with structurally shared vectors.) --- .../java8/runtime/CollectionInternals.java | 7 +++ .../converterImpl/StepsLikeIndexed.scala | 3 + .../java8/converterImpl/StepsVector.scala | 58 +++++++++++++++++-- .../compat/java8/StreamConvertersTest.scala | 28 +++++++++ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 6f8da89..901a3d5 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -5,12 +5,19 @@ public class CollectionInternals { public static Object[] getTable(scala.collection.mutable.FlatHashTable fht) { return fht.hashTableContents().table(); } public static > scala.collection.mutable.HashEntry[] getTable(scala.collection.mutable.HashTable ht) { return ht.hashTableContents().table(); } + public static boolean getDirt(scala.collection.immutable.Vector v) { return v.dirty(); } public static Object[] getDisplay0(scala.collection.immutable.Vector v) { return v.display0(); } + public static Object[] getDisplay0(scala.collection.immutable.VectorIterator p) { return p.display0(); } public static Object[] getDisplay1(scala.collection.immutable.Vector v) { return v.display1(); } + public static Object[] getDisplay1(scala.collection.immutable.VectorIterator p) { return p.display1(); } public static Object[] getDisplay2(scala.collection.immutable.Vector v) { return v.display2(); } + public static Object[] getDisplay2(scala.collection.immutable.VectorIterator p) { return p.display2(); } public static Object[] getDisplay3(scala.collection.immutable.Vector v) { return v.display3(); } + public static Object[] getDisplay3(scala.collection.immutable.VectorIterator p) { return p.display3(); } public static Object[] getDisplay4(scala.collection.immutable.Vector v) { return v.display4(); } + public static Object[] getDisplay4(scala.collection.immutable.VectorIterator p) { return p.display4(); } public static Object[] getDisplay5(scala.collection.immutable.Vector v) { return v.display5(); } + public static Object[] getDisplay5(scala.collection.immutable.VectorIterator p) { return p.display5(); } public static scala.Tuple2< scala.Tuple2< scala.collection.Iterator, Object >, scala.collection.Iterator > trieIteratorSplit(scala.collection.Iterator it) { if (it instanceof scala.collection.immutable.TrieIterator) { scala.collection.immutable.TrieIterator trie = (scala.collection.immutable.TrieIterator)it; diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index ed5abfa..8e3d312 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -32,16 +32,19 @@ private[java8] abstract class StepsLikeIndexed[A, STA >: Null <: StepsLikeIndexe private[java8] abstract class StepsDoubleLikeIndexed[STD >: Null <: StepsDoubleLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[DoubleStepper, STD](_i0, _iN) with DoubleStepper + with java.util.Spliterator.OfDouble // Compiler wants this for mixin forwarder {} /** Abstracts the operation of stepping over an indexable collection of Ints */ private[java8] abstract class StepsIntLikeIndexed[STI >: Null <: StepsIntLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[IntStepper, STI](_i0, _iN) with IntStepper + with java.util.Spliterator.OfInt // Compiler wants this for mixin forwarder {} /** Abstracts the operation of stepping over an indexable collection of Longs */ private[java8] abstract class StepsLongLikeIndexed[STL >: Null <: StepsLongLikeIndexed[_]](_i0: Int, _iN: Int) extends AbstractStepsLikeIndexed[LongStepper, STL](_i0, _iN) with LongStepper + with java.util.Spliterator.OfLong // Compiler wants this for mixin forwarder {} diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index b0abe26..11fe5ec 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -2,6 +2,8 @@ package scala.compat.java8.converterImpl import scala.annotation.switch +import scala.collection.immutable.VectorIterator + import scala.compat.java8.collectionImpl._ import scala.compat.java8.runtime._ @@ -13,20 +15,27 @@ import Stepper._ private[java8] trait StepsVectorLike[A] { protected def myVector: Vector[A] + protected def myVectorIterator: VectorIterator[A] + protected def myVectorLength: Int protected var index: Int = 32 protected var data: Array[AnyRef] = null protected var index1: Int = 32 protected var data1: Array[AnyRef] = null protected final def advanceData(iX: Int): Unit = { index1 += 1 - if (index >= 32) initTo(iX) + if (index >= 32) { + if (myVector != null) initTo(iX) + else initVpTo(iX) + } else { data = data1(index1).asInstanceOf[Array[AnyRef]] index = 0 } } protected final def initTo(iX: Int): Unit = { - myVector.length match { + // WARNING--initVpTo is an exact copy of this except for the type! If you change one you must change the other! + // (Manually specialized this way for speed.) + myVectorLength match { case x if x <= 0x20 => index = iX data = CollectionInternals.getDisplay0(myVector) @@ -52,12 +61,43 @@ private[java8] trait StepsVectorLike[A] { data = data1(index1).asInstanceOf[Array[AnyRef]] } } + protected final def initVpTo(iX: Int): Unit = { + // WARNING--this is an exact copy of initTo! If you change one you must change the other! + // (Manually specialized this way for speed.) + myVectorLength match { + case x if x <= 0x20 => + index = iX + data = CollectionInternals.getDisplay0(myVectorIterator) + case x if x <= 0x400 => + index1 = iX >>> 5 + data1 = CollectionInternals.getDisplay1(myVectorIterator) + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + case x => + var N = 0 + var dataN: Array[AnyRef] = + if (x <= 0x8000) { N = 2; CollectionInternals.getDisplay2(myVectorIterator) } + else if (x <= 0x100000) { N = 3; CollectionInternals.getDisplay3(myVectorIterator) } + else if (x <= 0x2000000) { N = 4; CollectionInternals.getDisplay4(myVectorIterator) } + else /*x <= 0x40000000*/{ N = 5; CollectionInternals.getDisplay5(myVectorIterator) } + while (N > 2) { + dataN = dataN((iX >>> (5*N))&0x1F).asInstanceOf[Array[AnyRef]] + N -= 1 + } + index1 = (iX >>> 5) & 0x1F + data1 = dataN((iX >>> 10) & 0x1F).asInstanceOf[Array[AnyRef]] + index = iX & 0x1F + data = data1(index1).asInstanceOf[Array[AnyRef]] + } + } } private[java8] class StepsAnyVector[A](underlying: Vector[A], _i0: Int, _iN: Int) extends StepsLikeIndexed[A, StepsAnyVector[A]](_i0, _iN) with StepsVectorLike[A] { - protected def myVector = underlying + protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying + protected val myVectorIterator = if (myVector == null) underlying.iterator else null + protected val myVectorLength = underlying.length def next() = if (hasNext()) { index += 1 if (index >= 32) advanceData(i0) @@ -76,7 +116,9 @@ with StepsVectorLike[A] { private[java8] class StepsDoubleVector(underlying: Vector[Double], _i0: Int, _iN: Int) extends StepsDoubleLikeIndexed[StepsDoubleVector](_i0, _iN) with StepsVectorLike[Double] { - protected def myVector = underlying + protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying + protected val myVectorIterator = if (myVector == null) underlying.iterator else null + protected val myVectorLength = underlying.length def nextDouble() = if (hasNext()) { index += 1 if (index >= 32) advanceData(i0) @@ -95,7 +137,9 @@ with StepsVectorLike[Double] { private[java8] class StepsIntVector(underlying: Vector[Int], _i0: Int, _iN: Int) extends StepsIntLikeIndexed[StepsIntVector](_i0, _iN) with StepsVectorLike[Int] { - protected def myVector = underlying + protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying + protected val myVectorIterator = if (myVector == null) underlying.iterator else null + protected val myVectorLength = underlying.length def nextInt() = if (hasNext()) { index += 1 if (index >= 32) advanceData(i0) @@ -114,7 +158,9 @@ with StepsVectorLike[Int] { private[java8] class StepsLongVector(underlying: Vector[Long], _i0: Int, _iN: Int) extends StepsLongLikeIndexed[StepsLongVector](_i0, _iN) with StepsVectorLike[Long] { - protected def myVector = underlying + protected val myVector = if (CollectionInternals.getDirt(underlying)) null else underlying + protected val myVectorIterator = if (myVector == null) underlying.iterator else null + protected val myVectorLength = underlying.length def nextLong() = if (hasNext()) { index += 1 if (index >= 32) advanceData(i0) diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index fbecae5..10a3f08 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -276,4 +276,32 @@ class StreamConvertersTest { val stepper2 = steppize2(coll2).stepper assertTrue(stepper2.getClass.getName.contains("StepsIntVector")) } + + @Test + def issue_87(): Unit = { + // Vectors that are generated from other vectors tend _not_ to + // have all their display vectors consistent; the cached vectors + // are correct, but the higher-level vector does _not_ contain + // the cached vector in the correct place (for efficiency)! This + // is called being "dirty", and needs to be handled specially. + val dirtyDisplayVector = Vector.fill(120)("a").slice(0, 40) + val shouldNotNPE = + dirtyDisplayVector.seqStream.collect(Collectors.toList()) + assertEq(shouldNotNPE.toArray(new Array[String](0)).toVector, dirtyDisplayVector, "Vector[Any].seqStream (with dirty display)") + + val dirtyDisplayVectorInt = Vector.fill(120)(999).slice(0, 40) + val shouldNotNPEInt = + dirtyDisplayVectorInt.seqStream.sum() + assertEq(shouldNotNPEInt, dirtyDisplayVectorInt.sum, "Vector[Int].seqStream (with dirty display)") + + val dirtyDisplayVectorLong = Vector.fill(120)(99999999999L).slice(0, 40) + val shouldNotNPELong = + dirtyDisplayVectorLong.seqStream.sum() + assertEq(shouldNotNPELong, dirtyDisplayVectorLong.sum, "Vector[Long].seqStream (with dirty display)") + + val dirtyDisplayVectorDouble = Vector.fill(120)(0.1).slice(0, 40) + val shouldNotNPEDouble = + math.rint(dirtyDisplayVectorDouble.seqStream.sum() * 10) + assertEq(shouldNotNPEDouble, math.rint(dirtyDisplayVectorDouble.sum * 10), "Vector[Double].seqStream (with dirty display)") + } } From 9a98a9dc309ec7122abb79462f65765c161ff173 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 20 Sep 2018 16:58:04 -0700 Subject: [PATCH 145/340] use .linesIterator to work around scala/bug#11125 this incurs a deprecation warning on 2.12.6, but we don't have fatal warnings enabled in this repo. the deprecation warnings will go away once we start building on 2.12.7. --- fnGen/WrapFnGen.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 5a953cb..f3d959a 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -58,12 +58,12 @@ object WrapFnGen { } implicit class SplitMyLinesAndStuff(s: String) { - def toVec = s.lines.toVector + def toVec = s.linesIterator.toVector def nonBlank = s.trim.length > 0 } implicit class TreeToText(t: Tree) { - def text = showCode(t).replace("$", "").lines.toVector + def text = showCode(t).replace("$", "").linesIterator.toVector } case class Prioritized(lines: Vector[String], priority: Int) { @@ -288,7 +288,7 @@ object WrapFnGen { def sameText(f: java.io.File, text: String): Boolean = { val x = scala.io.Source.fromFile(f) val lines = try { x.getLines.toVector } finally { x.close } - lines.iterator.filter(_.nonBlank) == text.lines.filter(_.nonBlank) + lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) } def write(f: java.io.File, text: String): Unit = { From c0af0315a6dd8820e06e147518606abb75673c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20Ol=C3=A1h?= Date: Sat, 6 Oct 2018 10:36:00 +0200 Subject: [PATCH 146/340] fix very small typo thie -> this typo fix --- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 61a2a6a..07265b1 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -11,7 +11,7 @@ import scala.concurrent.impl.Promise.DefaultPromise import scala.util.{ Try, Success, Failure } import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } -// TODO: make thie private[scala] when genjavadoc allows for that. +// TODO: make this private[scala] when genjavadoc allows for that. object FuturesConvertersImpl { def InternalCallbackExecutor = Future.InternalCallbackExecutor From 5079cb04d2c8e2b1efc6f2ad9928f0de366f8826 Mon Sep 17 00:00:00 2001 From: Scala steward Date: Thu, 11 Oct 2018 06:02:57 +0200 Subject: [PATCH 147/340] Update junit-interface to 0.11 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fbb4c54..8997cf8 100644 --- a/build.sbt +++ b/build.sbt @@ -52,7 +52,7 @@ lazy val root = (project in file(".")). libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test", - libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test", + libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", mimaPreviousVersion := None, From cc863d7206e989254ea35077335d518a24cfc38c Mon Sep 17 00:00:00 2001 From: Scala steward Date: Thu, 11 Oct 2018 06:03:03 +0200 Subject: [PATCH 148/340] Update junit to 4.12 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fbb4c54..77f27e3 100644 --- a/build.sbt +++ b/build.sbt @@ -48,7 +48,7 @@ lazy val root = (project in file(".")). OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), - libraryDependencies += "junit" % "junit" % "4.11" % "test", + libraryDependencies += "junit" % "junit" % "4.12" % "test", libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test", From 8a44d88a1a489256f878ea3da3823491244dfbe3 Mon Sep 17 00:00:00 2001 From: Scala steward Date: Thu, 11 Oct 2018 07:55:03 +0200 Subject: [PATCH 149/340] Update commons-lang3 to 3.8.1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9d4e685..8b06540 100644 --- a/build.sbt +++ b/build.sbt @@ -50,7 +50,7 @@ lazy val root = (project in file(".")). libraryDependencies += "junit" % "junit" % "4.12" % "test", - libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.4" % "test", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.8.1" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", From 19774f51579479ee2d864faf2d68b6510b2127b7 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 22 Sep 2018 19:53:36 +0900 Subject: [PATCH 150/340] remove SI-8449 workaround --- build.sbt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/build.sbt b/build.sbt index 8b06540..0209591 100644 --- a/build.sbt +++ b/build.sbt @@ -97,12 +97,7 @@ lazy val root = (project in file(".")). sys.error("Java 8 or higher is required for this project.") }, - publishArtifact in packageDoc := !disableDocs, - - sources in (Compile, doc) := { - val orig = (sources in (Compile, doc)).value - orig.filterNot(_.getName.endsWith(".java")) // raw types not cooked by scaladoc: https://issues.scala-lang.org/browse/SI-8449 - } + publishArtifact in packageDoc := !disableDocs ). settings( (inConfig(JavaDoc)(Defaults.configSettings) ++ (if (disableDocs) Nil else Seq( From aa5d87766613d21aca39227232cfa2f9d810f583 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Feb 2019 14:32:33 -0800 Subject: [PATCH 151/340] sbt 0.13.18 (was 0.13.17) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 133a8f1..8e682c5 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.17 +sbt.version=0.13.18 From ddde0619030d240a222008b61b2fb91d1ce49fa6 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Feb 2019 14:32:59 -0800 Subject: [PATCH 152/340] Scala 2.12.8 (was 2.12.6) --- .travis.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9d271a6..713eac5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ scala: # no 2.13 for now in cross-build because of # https://github.com/scala/scala-java8-compat/issues/97 - 2.11.12 - - 2.12.6 + - 2.12.8 env: global: diff --git a/build.sbt b/build.sbt index 8b06540..04afc19 100644 --- a/build.sbt +++ b/build.sbt @@ -2,7 +2,7 @@ import ScalaModulePlugin._ // no 2.13 for now in cross-build because of // https://github.com/scala/scala-java8-compat/issues/97 -crossScalaVersions in ThisBuild := List("2.12.6", "2.11.12") +crossScalaVersions in ThisBuild := List("2.12.8", "2.11.12") val disableDocs = sys.props("nodocs") == "true" From e82d1527746b0d49af1239c7cb7a67c58bb2f4d3 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 15 Feb 2019 14:41:52 -0800 Subject: [PATCH 153/340] ignore JDK 12 only warnings when compiling build definition --- project/plugins.sbt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index d283e84..1e7f7c0 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,8 @@ -scalacOptions += "-Xfatal-warnings" +scalacOptions ++= (sys.props("java.specification.version") match { + // work around weird dbuild thing for JDK 12 community build; see + // https://github.com/scala/community-builds/issues/862#issuecomment-464227096 + case "12" => Seq() + case _ => Seq("-Xfatal-warnings") +}) addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") From 52403642a270eb2902d668dea4af4f9fd32f695d Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Feb 2019 11:36:00 +0100 Subject: [PATCH 154/340] Relicense under Apache 2, closes #128 --- LICENSE | 229 +++++++++++++++--- benchmark/src/main/scala/bench/CodeGen.scala | 12 + .../main/scala/bench/CollectionSource.scala | 12 + .../src/main/scala/bench/Operations.scala | 12 + .../src/main/scala/bench/ParseJmhLog.scala | 12 + build.sbt | 4 + fnGen/WrapFnGen.scala | 10 +- project/CodeGen.scala | 10 +- .../compat/java8/ScalaStreamSupport.java | 12 + .../java8/runtime/CollectionInternals.java | 12 + .../java8/runtime/LambdaDeserializer.scala | 12 + .../IteratorPrimitiveDoubleWrapper.java | 11 +- .../wrappers/IteratorPrimitiveIntWrapper.java | 11 +- .../IteratorPrimitiveLongWrapper.java | 11 +- .../compat/java8/DurationConverters.scala | 11 +- .../scala/compat/java8/FutureConverters.scala | 11 +- .../scala/compat/java8/OptionConverters.scala | 11 +- .../java8/PrimitiveIteratorConversions.scala | 11 +- .../compat/java8/SpliteratorConverters.scala | 12 + .../scala/compat/java8/StreamConverters.scala | 12 + .../scala/compat/java8/WrapperTraits.scala | 12 + .../java8/collectionImpl/Accumulator.scala | 12 + .../collectionImpl/AccumulatorLike.scala | 12 + .../collectionImpl/DoubleAccumulator.scala | 12 + .../java8/collectionImpl/IntAccumulator.scala | 12 + .../collectionImpl/LongAccumulator.scala | 12 + .../compat/java8/collectionImpl/Stepper.scala | 12 + .../java8/converterImpl/Accumulates.scala | 12 + .../converterImpl/AccumulatorConverters.scala | 12 + .../java8/converterImpl/MakesSteppers.scala | 12 + .../java8/converterImpl/StepConverters.scala | 12 + .../java8/converterImpl/StepsArray.scala | 12 + .../java8/converterImpl/StepsBitSet.scala | 12 + .../converterImpl/StepsFlatHashTable.scala | 12 + .../java8/converterImpl/StepsHashTable.scala | 12 + .../java8/converterImpl/StepsImmHashMap.scala | 12 + .../java8/converterImpl/StepsImmHashSet.scala | 12 + .../java8/converterImpl/StepsIndexedSeq.scala | 12 + .../java8/converterImpl/StepsIterable.scala | 12 + .../java8/converterImpl/StepsIterator.scala | 12 + .../java8/converterImpl/StepsLikeGapped.scala | 12 + .../converterImpl/StepsLikeImmHashMap.scala | 12 + .../converterImpl/StepsLikeIndexed.scala | 12 + .../converterImpl/StepsLikeIterator.scala | 12 + .../java8/converterImpl/StepsLikeSliced.scala | 12 + .../converterImpl/StepsLikeTrieIterator.scala | 12 + .../java8/converterImpl/StepsLinearSeq.scala | 12 + .../compat/java8/converterImpl/StepsMap.scala | 12 + .../java8/converterImpl/StepsRange.scala | 12 + .../java8/converterImpl/StepsString.scala | 12 + .../java8/converterImpl/StepsVector.scala | 12 + .../java8/converterImpl/StepsWithTail.scala | 12 + .../java8/FutureConvertersImpl.scala | 11 +- .../java/scala/compat/java8/BoxingTest.java | 11 +- .../java8/DurationConvertersJavaTest.java | 11 +- .../compat/java8/FutureConvertersTest.java | 11 +- .../java/scala/compat/java8/LambdaTest.java | 11 +- .../compat/java8/OptionConvertersTest.scala | 11 +- .../scala/compat/java8/SpecializedTest.scala | 11 +- .../compat/java8/SpecializedTestSupport.java | 11 +- .../java8/StreamConvertersExampleTest.java | 10 +- .../java8/runtime/LambdaDeserializerTest.java | 12 + .../compat/java8/DurationConvertersTest.scala | 11 +- .../compat/java8/FunctionConvertersTest.scala | 12 + .../compat/java8/StepConvertersTest.scala | 12 + .../scala/compat/java8/StepperTest.scala | 12 + .../compat/java8/StreamConvertersTest.scala | 12 + 67 files changed, 944 insertions(+), 47 deletions(-) diff --git a/LICENSE b/LICENSE index d536dec..f49a4e1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,28 +1,201 @@ -Copyright (c) 2002-2018 EPFL -Copyright (c) 2011-2018 Lightbend, Inc. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the EPFL nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. \ No newline at end of file diff --git a/benchmark/src/main/scala/bench/CodeGen.scala b/benchmark/src/main/scala/bench/CodeGen.scala index 58976f6..53ede95 100644 --- a/benchmark/src/main/scala/bench/CodeGen.scala +++ b/benchmark/src/main/scala/bench/CodeGen.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package bench.codegen import scala.util._ diff --git a/benchmark/src/main/scala/bench/CollectionSource.scala b/benchmark/src/main/scala/bench/CollectionSource.scala index 2713543..07d021d 100644 --- a/benchmark/src/main/scala/bench/CollectionSource.scala +++ b/benchmark/src/main/scala/bench/CollectionSource.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package bench import java.util.stream._ diff --git a/benchmark/src/main/scala/bench/Operations.scala b/benchmark/src/main/scala/bench/Operations.scala index 0b795db..0a13126 100644 --- a/benchmark/src/main/scala/bench/Operations.scala +++ b/benchmark/src/main/scala/bench/Operations.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package bench.operate import java.util.stream._ diff --git a/benchmark/src/main/scala/bench/ParseJmhLog.scala b/benchmark/src/main/scala/bench/ParseJmhLog.scala index 90cc9d3..0263c45 100644 --- a/benchmark/src/main/scala/bench/ParseJmhLog.scala +++ b/benchmark/src/main/scala/bench/ParseJmhLog.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package bench.examine import scala.util._ diff --git a/build.sbt b/build.sbt index 6d3bb3d..10f155c 100644 --- a/build.sbt +++ b/build.sbt @@ -24,6 +24,10 @@ def osgiExport(scalaVersion: String, version: String) = { lazy val commonSettings = Seq( organization := "org.scala-lang.modules", version := "0.9.1-SNAPSHOT", + + // this line could be removed after https://github.com/scala/sbt-scala-module/issues/48 is fixed + licenses := Seq(("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0"))), + scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") ) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index f3d959a..b46dcce 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -1,5 +1,13 @@ /* - * Copyright (C) 2015-2016 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ object WrapFnGen { diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 250637a..4289973 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -1,5 +1,13 @@ /* - * Copyright (C) 2012-2016 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ sealed abstract class Type(val code: Char, val prim: String, val ref: String) { diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java/scala/compat/java8/ScalaStreamSupport.java index b0d3452..bc21ca8 100644 --- a/src/main/java/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java/scala/compat/java8/ScalaStreamSupport.java @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8; import scala.compat.java8.converterImpl.*; diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java index 6f8da89..1044ec5 100644 --- a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java/scala/compat/java8/runtime/CollectionInternals.java @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.runtime; // No imports! All type names are fully qualified to avoid confusion! diff --git a/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala b/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala index f9609d1..cdda56a 100644 --- a/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala +++ b/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.runtime import java.lang.invoke._ diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java index f863b8c..001699c 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8.wrappers; public class IteratorPrimitiveDoubleWrapper implements java.util.PrimitiveIterator.OfDouble { diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java index 10c5cf0..0e9a6fe 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8.wrappers; public class IteratorPrimitiveIntWrapper implements java.util.PrimitiveIterator.OfInt { diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java index 2cf799d..a78c736 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8.wrappers; public class IteratorPrimitiveLongWrapper implements java.util.PrimitiveIterator.OfLong { diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala index 27f3c46..854f9dc 100644 --- a/src/main/scala/scala/compat/java8/DurationConverters.scala +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2018 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import java.time.temporal.ChronoUnit diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 99f019a..2f95056 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import scala.language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/OptionConverters.scala b/src/main/scala/scala/compat/java8/OptionConverters.scala index 75b7915..49e06c2 100644 --- a/src/main/scala/scala/compat/java8/OptionConverters.scala +++ b/src/main/scala/scala/compat/java8/OptionConverters.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import java.util.{Optional, OptionalDouble, OptionalInt, OptionalLong} diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index f5a7a44..2d80ba6 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import java.util.{ Iterator => JIterator, PrimitiveIterator } diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala index a635c92..36838f3 100644 --- a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala +++ b/src/main/scala/scala/compat/java8/SpliteratorConverters.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala/scala/compat/java8/StreamConverters.scala index 4f773a9..00a3d24 100644 --- a/src/main/scala/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala/scala/compat/java8/StreamConverters.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/WrapperTraits.scala b/src/main/scala/scala/compat/java8/WrapperTraits.scala index da0125c..9106dfc 100644 --- a/src/main/scala/scala/compat/java8/WrapperTraits.scala +++ b/src/main/scala/scala/compat/java8/WrapperTraits.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 /** A trait that indicates that the class is or can be converted to a Scala version by wrapping a Java class */ diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala index 39f68ac..7358a1c 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala index 8201ac3..56519d2 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl /** An accumulator that works with Java 8 streams; it accepts elements of type `A`, diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index d43e40d..b082769 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala index d962d24..5054d26 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala index 06faa21..b924a71 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala index ffc94cb..8e13ea1 100644 --- a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.collectionImpl import scala.language.higherKinds diff --git a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala index cb3c963..ff40e53 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala index 8a43fd6..5b3e77f 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala index e194de9..e73e4d2 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala index 7fbf363..e6752dc 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import language.implicitConversions diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala index c9d21cf..d77daac 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala index 8b0a49c..279035b 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index 8661105..3ec1ae2 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala index f4869d6..f7a9f6c 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala index 4875a4a..0b7c329 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala index 84e0aff..864a3c2 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index 1065f0d..b7d2fe7 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala index b0d63e9..4343206 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala index d3b244f..62549a1 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala index 6f74880..27c3bff 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala index de4cdf1..e7ced1a 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index ed5abfa..56082d1 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala index 02a05c7..518cee3 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala index 8de1df0..ed3c695 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala index eeda5b9..78abd12 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala index 4c18398..d78c893 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala index 1bf71fa..c6e8862 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala index d364ed2..a4c92a3 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala index 66101a1..adc78f7 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala index b0abe26..c6cf1b8 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.annotation.switch diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala index f9977d7..04505a9 100644 --- a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala +++ b/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.compat.java8.collectionImpl._ diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 07265b1..31a6523 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.concurrent.java8 // Located in this package to access private[concurrent] members diff --git a/src/test/java/scala/compat/java8/BoxingTest.java b/src/test/java/scala/compat/java8/BoxingTest.java index c093631..e0a2c03 100644 --- a/src/test/java/scala/compat/java8/BoxingTest.java +++ b/src/test/java/scala/compat/java8/BoxingTest.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8; import org.junit.Test; diff --git a/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java b/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java index a032ae9..7d214a9 100644 --- a/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java +++ b/src/test/java/scala/compat/java8/DurationConvertersJavaTest.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2018 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8; import org.junit.Test; diff --git a/src/test/java/scala/compat/java8/FutureConvertersTest.java b/src/test/java/scala/compat/java8/FutureConvertersTest.java index 8022499..e3e492d 100644 --- a/src/test/java/scala/compat/java8/FutureConvertersTest.java +++ b/src/test/java/scala/compat/java8/FutureConvertersTest.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8; import org.junit.Test; diff --git a/src/test/java/scala/compat/java8/LambdaTest.java b/src/test/java/scala/compat/java8/LambdaTest.java index 7992f03..5127c18 100644 --- a/src/test/java/scala/compat/java8/LambdaTest.java +++ b/src/test/java/scala/compat/java8/LambdaTest.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8; import org.apache.commons.lang3.SerializationUtils; diff --git a/src/test/java/scala/compat/java8/OptionConvertersTest.scala b/src/test/java/scala/compat/java8/OptionConvertersTest.scala index a93b494..da99587 100644 --- a/src/test/java/scala/compat/java8/OptionConvertersTest.scala +++ b/src/test/java/scala/compat/java8/OptionConvertersTest.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import org.junit.Test diff --git a/src/test/java/scala/compat/java8/SpecializedTest.scala b/src/test/java/scala/compat/java8/SpecializedTest.scala index 7bd4a80..135c81f 100644 --- a/src/test/java/scala/compat/java8/SpecializedTest.scala +++ b/src/test/java/scala/compat/java8/SpecializedTest.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import org.junit.Test diff --git a/src/test/java/scala/compat/java8/SpecializedTestSupport.java b/src/test/java/scala/compat/java8/SpecializedTestSupport.java index 274926f..51f9cd2 100644 --- a/src/test/java/scala/compat/java8/SpecializedTestSupport.java +++ b/src/test/java/scala/compat/java8/SpecializedTestSupport.java @@ -1,6 +1,15 @@ /* - * Copyright (C) 2012-2015 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8; import java.util.Arrays; diff --git a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java index 33b1800..3a95f03 100644 --- a/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java +++ b/src/test/java/scala/compat/java8/StreamConvertersExampleTest.java @@ -1,5 +1,13 @@ /* - * Copyright (C) 2016 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ import org.junit.Test; diff --git a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java index 723e56c..6640a44 100644 --- a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java +++ b/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.runtime; import org.junit.Assert; diff --git a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala index 23c2304..443d40c 100644 --- a/src/test/scala/scala/compat/java8/DurationConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/DurationConvertersTest.scala @@ -1,6 +1,15 @@ /* - * Copyright (C) 2009-2018 Lightbend Inc. + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. */ + package scala.compat.java8 import java.time.{Duration => JavaDuration} diff --git a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala index 77881dd..b3da5ac 100644 --- a/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/FunctionConvertersTest.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import org.junit.Test diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala/scala/compat/java8/StepConvertersTest.scala index b7a43e4..d3e118c 100644 --- a/src/test/scala/scala/compat/java8/StepConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StepConvertersTest.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import org.junit.Test diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala/scala/compat/java8/StepperTest.scala index 48f3a8a..7bbbcd9 100644 --- a/src/test/scala/scala/compat/java8/StepperTest.scala +++ b/src/test/scala/scala/compat/java8/StepperTest.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import org.junit.Test diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala index fbecae5..1a63c86 100644 --- a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala +++ b/src/test/scala/scala/compat/java8/StreamConvertersTest.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 import scala.language.higherKinds From 96b4d6636c553a931d52d652a276777edce8ab40 Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Feb 2019 11:37:36 +0100 Subject: [PATCH 155/340] Update copyright header for auto-generated files --- fnGen/WrapFnGen.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index b46dcce..26acee7 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -14,7 +14,7 @@ object WrapFnGen { val copyright = s""" |/* - | * Copyright (C) 2015-2016, Lightbend Inc. + | * Copyright EPFL and Lightbend, Inc. | * This file auto-generated by WrapFnGen.scala. Do not modify directly. | */ |""".stripMargin From 5a25ea201acf6dec0e6a1426513d9a3f5feab34a Mon Sep 17 00:00:00 2001 From: Philippus Date: Sat, 16 Feb 2019 11:41:34 +0100 Subject: [PATCH 156/340] Add build status icon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f89b6d..2c5539f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## scala-java8-compat [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) +# scala-java8-compat [![Build Status](https://travis-ci.org/scala/scala-java8-compat.svg?branch=master)](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) A Java 8 compatibility kit for Scala. From 407df09cbd88310f5fafc52d91ee322b050f10e2 Mon Sep 17 00:00:00 2001 From: Will Sargent Date: Tue, 19 Feb 2019 08:59:05 -0800 Subject: [PATCH 157/340] Fix a typo s/FutureConverter/FutureConverters/ --- src/main/scala/scala/compat/java8/FutureConverters.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 2f95056..341f400 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -38,7 +38,7 @@ import java.util.function.Consumer * {{{ * import java.util.concurrent.CompletionStage; * import scala.concurrent.Future; - * import static scala.concurrent.java8.FutureConverter.*; + * import static scala.concurrent.java8.FutureConverters.*; * * final CompletionStage cs = ... // from an async Java API * final Future f = toScala(cs); From efb60c4e1f828d6dc0a4bf44814fe1b92fd54c65 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 19 Feb 2019 20:19:57 -0800 Subject: [PATCH 158/340] upgrade to sbt 1 --- admin/build.sh | 2 +- admin/gpg.sbt | 3 +-- build.sbt | 4 ---- project/build.properties | 2 +- project/plugins.sbt | 2 +- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/admin/build.sh b/admin/build.sh index db8692b..929aa55 100755 --- a/admin/build.sh +++ b/admin/build.sh @@ -29,7 +29,7 @@ if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then currentJvmVer=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | sed 's/^1\.//' | sed 's/[^0-9].*//') echo "Releasing $tagVer with Scala $TRAVIS_SCALA_VERSION on Java version $currentJvmVer." - publishTask="publish-signed" + publishTask="publishSigned" cat admin/gpg.sbt >> project/plugins.sbt cp admin/publish-settings.sbt . diff --git a/admin/gpg.sbt b/admin/gpg.sbt index d60e366..e6f00f4 100644 --- a/admin/gpg.sbt +++ b/admin/gpg.sbt @@ -1,2 +1 @@ - -addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3") // only added when publishing: +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2-1") // only added when publishing diff --git a/build.sbt b/build.sbt index 10f155c..e853b87 100644 --- a/build.sbt +++ b/build.sbt @@ -25,9 +25,6 @@ lazy val commonSettings = Seq( organization := "org.scala-lang.modules", version := "0.9.1-SNAPSHOT", - // this line could be removed after https://github.com/scala/sbt-scala-module/issues/48 is fixed - licenses := Seq(("Apache-2.0", url("https://www.apache.org/licenses/LICENSE-2.0"))), - scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") ) @@ -70,7 +67,6 @@ lazy val root = (project in file(".")). val runTarget = (mainClass in Compile in fnGen).value getOrElse "No main class defined for function conversion generator" val classPath = (fullClasspath in Compile in fnGen).value runner.value.run(runTarget, classPath.files, args, streams.value.log) - .foreach(sys.error) (out ** "*.scala").get }.taskValue, diff --git a/project/build.properties b/project/build.properties index 8e682c5..c0bab04 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.18 +sbt.version=1.2.8 diff --git a/project/plugins.sbt b/project/plugins.sbt index 1e7f7c0..2de9ecd 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -5,4 +5,4 @@ scalacOptions ++= (sys.props("java.specification.version") match { case _ => Seq("-Xfatal-warnings") }) -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "1.0.14") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.0.0") From 2a28f25d87c89c997a31218d01f8fcc7c390374c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 6 Mar 2019 14:40:42 -0800 Subject: [PATCH 159/340] add OpenJDK 11 to CI matrix fixes #130 --- .travis.yml | 1 + build.sbt | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 713eac5..c8f9482 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ sudo: false jdk: - oraclejdk8 + - openjdk11 scala: # no 2.13 for now in cross-build because of diff --git a/build.sbt b/build.sbt index e853b87..cf9c21e 100644 --- a/build.sbt +++ b/build.sbt @@ -4,7 +4,10 @@ import ScalaModulePlugin._ // https://github.com/scala/scala-java8-compat/issues/97 crossScalaVersions in ThisBuild := List("2.12.8", "2.11.12") -val disableDocs = sys.props("nodocs") == "true" +val disableDocs = + sys.props("nodocs") == "true" || + // can't build doc on JDK 11 until sbt/sbt#4350 is fixed + !sys.props("java.version").startsWith("1.") lazy val JavaDoc = config("genjavadoc") extend Compile From 490473ccc5c4ed7046231c271a56192d58f86fd0 Mon Sep 17 00:00:00 2001 From: Filippo De Luca Date: Thu, 14 Mar 2019 16:08:25 +0000 Subject: [PATCH 160/340] Fix the DurationConverters import in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2c5539f..5d0800c 100644 --- a/README.md +++ b/README.md @@ -268,7 +268,7 @@ Example of conversions from the Java type ways: ```scala import scala.concurrent.duration._ -import scala.compat.java8.DurationConverters +import scala.compat.java8.DurationConverters._ val javaDuration: java.time.Duration = 5.seconds.toJava val finiteDuration: FiniteDuration = javaDuration.toScala From b8415dbc6f3775e3224597aeb1751afc6105028c Mon Sep 17 00:00:00 2001 From: Scala steward Date: Wed, 27 Mar 2019 23:12:24 +0100 Subject: [PATCH 161/340] Update genjavadoc-plugin to 0.13 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index cf9c21e..f9493cc 100644 --- a/build.sbt +++ b/build.sbt @@ -113,7 +113,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.11" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.13" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From e52c5b8d51fded3e95f0187f99bb88150465c992 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 22 Apr 2019 19:50:56 -0700 Subject: [PATCH 162/340] add CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..0511f21 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,7 @@ +all repositories in these organizations: + +* [scala](https://github.com/scala) +* [scalacenter](https://github.com/scalacenter) +* [lampepfl](https://github.com/lampepfl) + +are covered by the Scala Code of Conduct: https://scala-lang.org/conduct/ From 1167576e9989bff52ffd6d1908b9cea06e1d9e92 Mon Sep 17 00:00:00 2001 From: Scala steward Date: Tue, 23 Apr 2019 13:28:07 +0200 Subject: [PATCH 163/340] Update commons-lang3 to 3.9 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f9493cc..2817ffc 100644 --- a/build.sbt +++ b/build.sbt @@ -54,7 +54,7 @@ lazy val root = (project in file(".")). libraryDependencies += "junit" % "junit" % "4.12" % "test", - libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.8.1" % "test", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.9" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", From 0989d02c318ae91c69f50f497e926661ab3e1ef8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 23 Apr 2019 16:37:45 -0700 Subject: [PATCH 164/340] add missing NOTICE file --- LICENSE | 2 +- NOTICE | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 NOTICE diff --git a/LICENSE b/LICENSE index f49a4e1..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -198,4 +198,4 @@ 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. \ No newline at end of file + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..e4ab773 --- /dev/null +++ b/NOTICE @@ -0,0 +1,14 @@ +scala-java8-compat +Copyright (c) 2002-2019 EPFL +Copyright (c) 2011-2019 Lightbend, Inc. + +scala-java8-compat includes software developed at +LAMP/EPFL (https://lamp.epfl.ch/) and +Lightbend, Inc. (https://www.lightbend.com/). + +Licensed under the Apache License, Version 2.0 (the "License"). +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. From 61a04abdda85158f5eb5d3212179413d94c0d9b1 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 4 Jul 2019 20:04:23 +0200 Subject: [PATCH 165/340] update Travis-CI setup: use OpenJDK 8 we are standardizing on this for all the modules, most were changed already, this one was not --- .travis.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c8f9482..63c835a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,11 @@ language: scala -sudo: false - jdk: - - oraclejdk8 + - openjdk8 - openjdk11 scala: - # no 2.13 for now in cross-build because of - # https://github.com/scala/scala-java8-compat/issues/97 + # note that 2.13 is on the 2.13.x branch instead - 2.11.12 - 2.12.8 From 474eac28b60760e1580ce191e2f6c4c0e7eccb0c Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 9 Jul 2019 12:45:02 -0400 Subject: [PATCH 166/340] Use AdoptOpenJDK JDK 8 and 11 Ref https://github.com/scala/scala-dev/issues/587 --- .travis.yml | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 63c835a..591b290 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ language: scala -jdk: - - openjdk8 - - openjdk11 - scala: # note that 2.13 is on the 2.13.x branch instead - 2.11.12 @@ -17,6 +13,22 @@ env: - secure: "lx2qFeFxh9AFmyHR7hH4Qf9flIEx8VgYj6ebzuxp1cc1ZZiXHC1256x0bHFDUH9bhJACOazOrco/+v6MBAriBkWxLBc98FrC6OkVeQMFW2ffWSBuHRclilKsQA/Lsgc81Wg+WV105hOqUNAkTXgroblInNt+KS+DhC/8FVoh9ZY=" # SONA_PASS - secure: "FZC+FZnBNeklA150vW5QDZJ5J7t+DExJrgyXWM46Wh0MobjH8cvydgC3qatItb0rDBV8l7zO1LDwl2KEi92aefw2a8E49z6qVOHgUXiI3SAx7M0UO0FFeKPmTXCLcBlbnGLcUqNjIZfuIEufQvPblKTl8qN4eMmcMn9jsNzJr28=" + matrix: + - ADOPTOPENJDK=8 + - ADOPTOPENJDK=11 + +before_install: + # adding $HOME/.sdkman to cache would create an empty directory, which interferes with the initial installation + - "[[ -d $HOME/.sdkman/bin/ ]] || rm -rf $HOME/.sdkman/" + - curl -sL https://get.sdkman.io | bash + - echo sdkman_auto_answer=true > $HOME/.sdkman/etc/config + - source "$HOME/.sdkman/bin/sdkman-init.sh" + +install: + - sdk install java $(sdk list java | grep -o "$ADOPTOPENJDK\.[0-9\.]*hs-adpt" | head -1) + - unset JAVA_HOME + - java -Xmx32m -version + - javac -J-Xmx32m -version script: - admin/build.sh @@ -25,3 +37,12 @@ notifications: email: - jason.zaugg@lightbend.com - seth.tisue@lightbend.com + +before_cache: + - find $HOME/.sbt -name "*.lock" | xargs rm + - find $HOME/.ivy2/cache -name "ivydata-*.properties" | xargs rm +cache: + directories: + - $HOME/.ivy2/cache + - $HOME/.sbt + - $HOME/.sdkman From a30b2fdf38b1cbb243bdbb9c3cdc4c7894b4505a Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 16 Jul 2019 14:12:35 +0200 Subject: [PATCH 167/340] Integrate 2.13.x branch into master Use version-specific source directories where necessary. --- .travis.yml | 4 +- README.md | 2 +- build.sbt | 26 +- fnGen/WrapFnGen.scala | 4 +- project/CodeGen.scala | 4 +- .../compat/java8/ScalaStreamSupport.java | 384 ++++++++++++ .../compat/java8/ScalaStreamSupport.java | 0 .../java8/runtime/CollectionInternals.java | 0 .../java8/runtime/LambdaDeserializer.scala | 5 +- .../scala/compat/java8/StreamConverters.scala | 506 ++++++++++++++++ .../compat/java8/collectionImpl/package.scala | 30 + .../java8/converterImpl/Accumulates.scala | 47 ++ .../converterImpl/AccumulatorConverters.scala | 32 + .../converterImpl/StepperExtensions.scala | 77 +++ .../java8/FuturesConvertersImplCompat.scala | 8 + .../compat/java8/SpliteratorConverters.scala | 0 .../scala/compat/java8/StreamConverters.scala | 0 .../java8/collectionImpl/Accumulator.scala | 0 .../collectionImpl/AccumulatorLike.scala | 0 .../collectionImpl/DoubleAccumulator.scala | 0 .../java8/collectionImpl/IntAccumulator.scala | 0 .../collectionImpl/LongAccumulator.scala | 0 .../compat/java8/collectionImpl/Stepper.scala | 0 .../java8/converterImpl/Accumulates.scala | 0 .../converterImpl/AccumulatorConverters.scala | 0 .../java8/converterImpl/MakesSteppers.scala | 0 .../java8/converterImpl/StepConverters.scala | 0 .../java8/converterImpl/StepsArray.scala | 0 .../java8/converterImpl/StepsBitSet.scala | 0 .../converterImpl/StepsFlatHashTable.scala | 0 .../java8/converterImpl/StepsHashTable.scala | 0 .../java8/converterImpl/StepsImmHashMap.scala | 0 .../java8/converterImpl/StepsImmHashSet.scala | 0 .../java8/converterImpl/StepsIndexedSeq.scala | 0 .../java8/converterImpl/StepsIterable.scala | 0 .../java8/converterImpl/StepsIterator.scala | 0 .../java8/converterImpl/StepsLikeGapped.scala | 0 .../converterImpl/StepsLikeImmHashMap.scala | 0 .../converterImpl/StepsLikeIndexed.scala | 0 .../converterImpl/StepsLikeIterator.scala | 0 .../java8/converterImpl/StepsLikeSliced.scala | 0 .../converterImpl/StepsLikeTrieIterator.scala | 0 .../java8/converterImpl/StepsLinearSeq.scala | 0 .../compat/java8/converterImpl/StepsMap.scala | 0 .../java8/converterImpl/StepsRange.scala | 0 .../java8/converterImpl/StepsString.scala | 0 .../java8/converterImpl/StepsVector.scala | 0 .../java8/converterImpl/StepsWithTail.scala | 0 .../java8/FuturesConvertersImplCompat.scala | 8 + .../scala/compat/java8/FutureConverters.scala | 1 + .../java8/PrimitiveIteratorConversions.scala | 12 +- .../java8/FutureConvertersImpl.scala | 15 +- .../java8/runtime/LambdaDeserializerTest.java | 0 .../java/scala/compat/java8/BoxingTest.java | 6 +- .../compat/java8/StepConvertersTest.scala | 565 ++++++++++++++++++ .../scala/compat/java8/StepperTest.scala | 319 ++++++++++ .../compat/java8/StreamConvertersTest.scala | 303 ++++++++++ .../compat/java8/StepConvertersTest.scala | 0 .../scala/compat/java8/StepperTest.scala | 0 .../compat/java8/StreamConvertersTest.scala | 0 60 files changed, 2329 insertions(+), 29 deletions(-) create mode 100644 src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java rename src/main/{java => java-2.13-}/scala/compat/java8/ScalaStreamSupport.java (100%) rename src/main/{java => java-2.13-}/scala/compat/java8/runtime/CollectionInternals.java (100%) rename src/main/{java => scala-2.11}/scala/compat/java8/runtime/LambdaDeserializer.scala (97%) create mode 100644 src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala create mode 100644 src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala create mode 100644 src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala create mode 100644 src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala create mode 100644 src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala create mode 100644 src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala rename src/main/{scala => scala-2.13-}/scala/compat/java8/SpliteratorConverters.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/StreamConverters.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/Accumulator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/AccumulatorLike.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/DoubleAccumulator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/IntAccumulator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/LongAccumulator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/collectionImpl/Stepper.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/Accumulates.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/AccumulatorConverters.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/MakesSteppers.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepConverters.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsArray.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsBitSet.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsFlatHashTable.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsHashTable.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsImmHashMap.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsImmHashSet.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsIndexedSeq.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsIterable.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsIterator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeGapped.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeIndexed.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeIterator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeSliced.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsLinearSeq.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsMap.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsRange.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsString.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsVector.scala (100%) rename src/main/{scala => scala-2.13-}/scala/compat/java8/converterImpl/StepsWithTail.scala (100%) create mode 100644 src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala rename src/test/{java => java-2.11}/scala/compat/java8/runtime/LambdaDeserializerTest.java (100%) create mode 100644 src/test/scala-2.13+/scala/compat/java8/StepConvertersTest.scala create mode 100644 src/test/scala-2.13+/scala/compat/java8/StepperTest.scala create mode 100644 src/test/scala-2.13+/scala/compat/java8/StreamConvertersTest.scala rename src/test/{scala => scala-2.13-}/scala/compat/java8/StepConvertersTest.scala (100%) rename src/test/{scala => scala-2.13-}/scala/compat/java8/StepperTest.scala (100%) rename src/test/{scala => scala-2.13-}/scala/compat/java8/StreamConvertersTest.scala (100%) diff --git a/.travis.yml b/.travis.yml index 591b290..a0e622d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: scala scala: - # note that 2.13 is on the 2.13.x branch instead - - 2.11.12 + - 2.13.0 - 2.12.8 + - 2.11.12 env: global: diff --git a/README.md b/README.md index 5d0800c..f5bb5b5 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ as the collection can (in some cases) be built in parallel. Because the wrappers are invoked based on the static type of the collection, there are also cases where parallelization is inefficient when interfacing with Java 8 Streams (e.g. when a collection is typed as `Seq[String]` so might have linear -access like `List`, but actually is a `WrappedArray[String]` that can be efficiently parallelized) but can be efficient +access like `List`, but actually is a `WrappedArray[String]` (`ArraySeq` on 2.13) that can be efficiently parallelized) but can be efficient with Scala parallel collections. The `parStream` method is only available when the static type is known to be compatible with rapid parallel operation; `seqStream` can be parallelized by using `.parallel`, but may or may not be efficient. diff --git a/build.sbt b/build.sbt index 2817ffc..3a2b463 100644 --- a/build.sbt +++ b/build.sbt @@ -1,8 +1,6 @@ import ScalaModulePlugin._ -// no 2.13 for now in cross-build because of -// https://github.com/scala/scala-java8-compat/issues/97 -crossScalaVersions in ThisBuild := List("2.12.8", "2.11.12") +crossScalaVersions in ThisBuild := List("2.13.0", "2.12.8", "2.11.12") val disableDocs = sys.props("nodocs") == "true" || @@ -28,7 +26,27 @@ lazy val commonSettings = Seq( organization := "org.scala-lang.modules", version := "0.9.1-SNAPSHOT", - scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") + scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked"), + + unmanagedSourceDirectories in Compile ++= { + (unmanagedSourceDirectories in Compile).value.flatMap { dir => + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) + case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) + case _ => Seq(file(dir.getPath ++ "-2.13-")) + } + } + }, + + unmanagedSourceDirectories in Test ++= { + (unmanagedSourceDirectories in Test).value.flatMap { dir => + CrossVersion.partialVersion(scalaVersion.value) match { + case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) + case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) + case _ => Seq(file(dir.getPath ++ "-2.13-")) + } + } + }, ) lazy val fnGen = (project in file("fnGen")). diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index 26acee7..c3e2e86 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -245,7 +245,7 @@ object WrapFnGen { numberedA ++= scalaTargs.map(_.toString).collect{ case An(digits) if (digits.length < 10) => digits.toInt } val scalafnTnames = (jfn.pTypes :+ jfn.rType).zipWithIndex.map{ case (pt, i) if (i < jfn.pTypes.length && pt.isFinalType) || (!pt.isFinalType && jfn.pTypes.take(i).exists(_ == pt)) => - val j = Iterator.from(i).dropWhile(numberedA).next + val j = Iterator.from(i).dropWhile(numberedA).next() val genericName = TypeName(s"A$j") numberedA += j evidences += ((genericName, pt.typeSymbol.name.toTypeName)) @@ -309,6 +309,6 @@ object WrapFnGen { def main(args: Array[String]): Unit = { val names = args.iterator.map(x => new java.io.File(x)) - write(names.next, converterContents) + write(names.next(), converterContents) } } diff --git a/project/CodeGen.scala b/project/CodeGen.scala index 4289973..b3f3f11 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -519,9 +519,9 @@ object CodeGen { val specialized = List("V", "V,IJFD", "V,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => - s" public static scala.Function$i<$a> procSpecialized(JFunction$i$sp f) { return f; }" } ++ + s" public static scala.Function$i<$a> procSpecialized(JFunction$i$sp f) { return (scala.Function$i<$a>)(Object)f; }" } ++ List("BSIJCFDZ", "ZIFJD,IJFD", "ZIFJD,IJD,IJD").flatMap(specialize).map { case (i, a, sp) => - s" public static scala.Function$i<$a> funcSpecialized(JFunction$i$sp f) { return f; }" } + s" public static scala.Function$i<$a> funcSpecialized(JFunction$i$sp f) { return (scala.Function$i<$a>)(Object)f; }" } (blocks.map(_._1) ++ blocks.map(_._2)) :+ ( "JFunction", diff --git a/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java b/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java new file mode 100644 index 0000000..af78ecd --- /dev/null +++ b/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java @@ -0,0 +1,384 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8; + +import java.util.stream.*; + +import scala.collection.*; +import scala.jdk.javaapi.StreamConverters; + +/** + * This class contains static utility methods for creating Java Streams from Scala Collections, similar + * to the methods in {@code java.util.stream.StreamSupport} for other Java types. It is intended for + * use from Java code. In Scala code, you can use the extension methods provided by + * {@code scala.compat.java8.StreamConverters} instead. + * + * Streams created from immutable Scala collections are also immutable. Mutable collections should + * not be modified concurrently. There are no guarantees for success or failure modes of existing + * streams in case of concurrent modifications. + */ +public class ScalaStreamSupport { + ///////////////////// + // Generic Streams // + ///////////////////// + + /** + * Generates a Stream that traverses a Scala collection. + *

+ * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. + * + * @param coll The IterableOnce to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream stream(IterableOnce coll) { + return StreamConverters.asJavaSeqStream(coll); + } + + /** + * Generates a Stream that traverses the keys of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream streamKeys(Map coll) { + return StreamSupport.stream(coll.keyStepper(StepperShape.anyStepperShape()).spliterator(), false); + } + + /** + * Generates a Stream that traverses the values of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream streamValues(Map coll) { + return StreamSupport.stream(coll.>valueStepper(StepperShape.anyStepperShape()).spliterator(), false); + } + + /** + * Generates a Stream that traverses the key-value pairs of a scala.collection.Map. + *

+ * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream< scala.Tuple2 > stream(Map coll) { + return StreamConverters.asJavaSeqStream(coll); + } + + /** + * Generates a Stream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream streamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll)); + } + + /** + * Generates a Stream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream streamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll.keysIterator())); + } + + /** + * Generates a Stream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A Stream view of the collection which, by default, executes sequentially. + */ + public static Stream streamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqStream(scala.jdk.AnyAccumulator.from(coll.valuesIterator())); + } + + //////////////////// + // Double Streams // + //////////////////// + + /** + * Generates a DoubleStream that traverses a Scala collection. + *

+ * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. + * + * @param coll The IterableOnce to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStream(IterableOnce coll) { + return StreamConverters.asJavaSeqDoubleStream(coll); + } + + /** + * Generates a DoubleStream that traverses the keys of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStreamKeys(Map coll) { + return StreamSupport.doubleStream(coll.keyStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); + } + + /** + * Generates a DoubleStream that traverses the values of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStreamValues(Map coll) { + return StreamSupport.doubleStream(coll.valueStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); + } + + /** + * Generates a DoubleStream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqDoubleStream((IterableOnce)(Object)scala.jdk.DoubleAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll)); + } + + /** + * Generates a DoubleStream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqDoubleStream((IterableOnce)(Object)scala.jdk.DoubleAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.keysIterator())); + } + + /** + * Generates a DoubleStream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A DoubleStream view of the collection which, by default, executes sequentially. + */ + public static DoubleStream doubleStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqDoubleStream((IterableOnce)(Object)scala.jdk.DoubleAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.valuesIterator())); + } + + ///////////////// + // Int Streams // + ///////////////// + + /** + * Generates a IntStream that traverses a Scala collection. + *

+ * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. + * + * @param coll The IterableOnce to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStream(IterableOnce coll) { + return StreamConverters.asJavaSeqIntStream(coll); + } + + /** + * Generates a IntStream that traverses the keys of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStreamKeys(Map coll) { + return StreamSupport.intStream(coll.keyStepper((StepperShape)(Object)StepperShape.intStepperShape()).spliterator(), false); + } + + /** + * Generates a IntStream that traverses the values of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStreamValues(Map coll) { + return StreamSupport.intStream(coll.valueStepper((StepperShape)(Object)StepperShape.intStepperShape()).spliterator(), false); + } + + /** + * Generates a IntStream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqIntStream((IterableOnce)(Object)scala.jdk.IntAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll)); + } + + /** + * Generates a IntStream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqIntStream((IterableOnce)(Object)scala.jdk.IntAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.keysIterator())); + } + + /** + * Generates a IntStream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A IntStream view of the collection which, by default, executes sequentially. + */ + public static IntStream intStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqIntStream((IterableOnce)(Object)scala.jdk.IntAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.valuesIterator())); + } + + ////////////////// + // Long Streams // + ////////////////// + + /** + * Generates a LongStream that traverses a Scala collection. + *

+ * Parallel processing is only efficient for collections that have a Stepper implementation + * which supports efficient splitting. For collections where this is the case, the stepper + * method has a return type marked with EfficientSplit. + * + * @param coll The IterableOnce to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStream(IterableOnce coll) { + return StreamConverters.asJavaSeqLongStream(coll); + } + + /** + * Generates a LongStream that traverses the keys of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a keyStepper implementation + * which supports efficient splitting. For collections where this is the case, the keyStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStreamKeys(Map coll) { + return StreamSupport.longStream(coll.keyStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); + } + + /** + * Generates a LongStream that traverses the values of a scala.collection.Map. + *

+ * Parallel processing is only efficient for Maps that have a valueStepper implementation + * which supports efficient splitting. For collections where this is the case, the valueStepper + * method has a return type marked with EfficientSplit. + * + * @param coll The Map to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStreamValues(Map coll) { + return StreamSupport.longStream(coll.valueStepper((StepperShape)(Object)StepperShape.doubleStepperShape()).spliterator(), false); + } + + /** + * Generates a LongStream that traverses any Scala collection by accumulating its entries + * into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The collection to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStreamAccumulated(IterableOnce coll) { + return StreamConverters.asJavaSeqLongStream((IterableOnce)(Object)scala.jdk.LongAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll)); + } + + /** + * Generates a LongStream that traverses the keys of any Scala map by + * accumulating those keys into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing keys to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStreamAccumulatedKeys(Map coll) { + return StreamConverters.asJavaSeqLongStream((IterableOnce)(Object)scala.jdk.LongAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.keysIterator())); + } + + /** + * Generates a LongStream that traverses the values of any Scala map by + * accumulating those values into a buffer class (Accumulator). + *

+ * Both sequential and parallel operations will be efficient. + * + * @param coll The map containing values to traverse + * @return A LongStream view of the collection which, by default, executes sequentially. + */ + public static LongStream longStreamAccumulatedValues(Map coll) { + return StreamConverters.asJavaSeqLongStream((IterableOnce)(Object)scala.jdk.LongAccumulator$.MODULE$.fromSpecific((IterableOnce)(Object)coll.valuesIterator())); + } +} diff --git a/src/main/java/scala/compat/java8/ScalaStreamSupport.java b/src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java similarity index 100% rename from src/main/java/scala/compat/java8/ScalaStreamSupport.java rename to src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java diff --git a/src/main/java/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java similarity index 100% rename from src/main/java/scala/compat/java8/runtime/CollectionInternals.java rename to src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java diff --git a/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala b/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala similarity index 97% rename from src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala rename to src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala index cdda56a..551e649 100644 --- a/src/main/java/scala/compat/java8/runtime/LambdaDeserializer.scala +++ b/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala @@ -15,8 +15,9 @@ package scala.compat.java8.runtime import java.lang.invoke._ /** - * This class is only intended to be called by synthetic `$deserializeLambda$` method that the Scala 2.12 - * compiler will add to classes hosting lambdas. + * This class is only intended to be called by synthetic `$deserializeLambda$` method that the + * Scala 2.11 compiler will add to classes hosting lambdas. In Scala 2.12+, it's part of the + * standard library. * * It is not intended to be consumed directly. */ diff --git a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala new file mode 100644 index 0000000..8adea5f --- /dev/null +++ b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala @@ -0,0 +1,506 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8 + +import java.util.stream._ + +import scala.annotation.{implicitNotFound, unused} +import scala.collection.Stepper.EfficientSplit +import scala.collection.convert.StreamExtensions.{AccumulatorFactoryInfo, StreamShape, StreamUnboxer} +import scala.collection.{IterableOnce, Stepper, StepperShape} +import scala.compat.java8.converterImpl._ +import scala.jdk.CollectionConverters._ +import scala.jdk._ +import scala.language.{higherKinds, implicitConversions} + +/** Defines extension methods to create Java Streams for Scala collections, available through + * [[scala.compat.java8.StreamConverters]]. + */ +trait StreamExtensions { + implicit def richStepper[A](s: Stepper[A]): StepperExtensions[A] = new StepperExtensions[A](s) + + // collections + + implicit class IterableHasSeqStream[A](cc: IterableOnce[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this collection. If the + * collection contains primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], st: StepperShape[A, St]): S = + s.fromStepper(cc.stepper, par = false) + } + + // Not `CC[X] <: IterableOnce[X]`, but `C` with an extra constraint, to support non-parametric classes like IntAccumulator + implicit class IterableNonGenericHasParStream[A, C <: IterableOnce[_]](c: C)(implicit ev: C <:< IterableOnce[A]) { + private type IterableOnceWithEfficientStepper = IterableOnce[A] { + def stepper[S <: Stepper[_]](implicit shape : StepperShape[A, S]) : S with EfficientSplit + } + + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this collection. If the + * collection contains primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[A, S, St], + st: StepperShape[A, St], + @implicitNotFound("`parStream` can only be called on collections where `stepper` returns a `Stepper with EfficientSplit`") + isEfficient: C <:< IterableOnceWithEfficientStepper): S = + s.fromStepper(ev(c).stepper, par = true) + } + + // maps + + implicit class MapHasSeqKeyValueStream[K, V, CC[X, Y] <: collection.MapOps[X, Y, collection.Map, _]](cc: CC[K, V]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the keys of this map. If + * the keys are primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqKeyStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[K, S, St], st: StepperShape[K, St]): S = + s.fromStepper(cc.keyStepper, par = false) + + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the values of this map. If + * the values are primitives, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqValueStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[V, S, St], st: StepperShape[V, St]): S = + s.fromStepper(cc.valueStepper, par = false) + + // The seqStream extension method for IterableOnce doesn't apply because its `CC` takes a single type parameter, whereas the one here takes two + /** Create a sequential [[java.util.stream.Stream Java Stream]] for the `(key, value)` pairs of + * this map. + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[(K, V), S, St], st: StepperShape[(K, V), St]): S = + s.fromStepper(cc.stepper, par = false) + } + + + implicit class MapHasParKeyValueStream[K, V, CC[X, Y] <: collection.MapOps[X, Y, collection.Map, _]](cc: CC[K, V]) { + private type MapOpsWithEfficientKeyStepper = collection.MapOps[K, V, collection.Map, _] { def keyStepper[S <: Stepper[_]](implicit shape : StepperShape[K, S]) : S with EfficientSplit } + private type MapOpsWithEfficientValueStepper = collection.MapOps[K, V, collection.Map, _] { def valueStepper[V1 >: V, S <: Stepper[_]](implicit shape : StepperShape[V1, S]) : S with EfficientSplit } + private type MapOpsWithEfficientStepper = collection.MapOps[K, V, collection.Map, _] { def stepper[S <: Stepper[_]](implicit shape : StepperShape[(K, V), S]) : S with EfficientSplit } + + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the keys of this map. If + * the keys are primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parKeyStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[K, S, St], + st: StepperShape[K, St], + @implicitNotFound("parKeyStream can only be called on maps where `keyStepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientKeyStepper): S = + s.fromStepper(cc.keyStepper, par = true) + + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the values of this map. If + * the values are primitives, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parValueStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[V, S, St], + st: StepperShape[V, St], + @implicitNotFound("parValueStream can only be called on maps where `valueStepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientValueStepper): S = + s.fromStepper(cc.valueStepper, par = true) + + // The parStream extension method for IterableOnce doesn't apply because its `CC` takes a single type parameter, whereas the one here takes two + /** Create a parallel [[java.util.stream.Stream Java Stream]] for the `(key, value)` pairs of + * this map. + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit + s: StreamShape[(K, V), S, St], + st: StepperShape[(K, V), St], + @implicitNotFound("parStream can only be called on maps where `stepper` returns a `Stepper with EfficientSplit`") + isEfficient: CC[K, V] <:< MapOpsWithEfficientStepper): S = + s.fromStepper(cc.stepper, par = true) + } + + // steppers + + implicit class StepperHasSeqStream[A](stepper: Stepper[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this stepper. If the + * stepper yields primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def seqStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], @unused st: StepperShape[A, St]): S = + s.fromStepper(stepper.asInstanceOf[St], par = false) + } + + implicit class StepperHasParStream[A](stepper: Stepper[A] with EfficientSplit) { + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this stepper. If the + * stepper yields primitive values, a corresponding specialized Stream is returned (e.g., + * [[java.util.stream.IntStream `IntStream`]]). + */ + def parStream[S <: BaseStream[_, _], St <: Stepper[_]](implicit s: StreamShape[A, S, St], @unused st: StepperShape[A, St]): S = + s.fromStepper(stepper.asInstanceOf[St], par = true) + } + + // arrays + // uses the JDK array spliterators (`DoubleArraySpliterator`). users can also call + // `array.stepper.seqStream`, which then uses the Scala steppers (`DoubleArrayStepper`). the + // steppers are also available on byte/short/char/float arrays (`WidenedByteArrayStepper`), + // JDK spliterators only for double/int/long/reference. + + implicit class DoubleArrayHasSeqParStream(a: Array[Double]) { + /** Create a sequential [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def seqStream: DoubleStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def parStream: DoubleStream = seqStream.parallel + } + + implicit class IntArrayHasSeqParStream(a: Array[Int]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = seqStream.parallel + } + + implicit class LongArrayHasSeqParStream(a: Array[Long]) { + /** Create a sequential [[java.util.stream.LongStream Java LongStream]] for this array. */ + def seqStream: LongStream = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.LongStream Java LongStream]] for this array. */ + def parStream: LongStream = seqStream.parallel + } + + implicit class AnyArrayHasSeqParStream[A <: AnyRef](a: Array[A]) { + /** Create a sequential [[java.util.stream.Stream Java Stream]] for this array. */ + def seqStream: Stream[A] = java.util.Arrays.stream(a) + /** Create a parallel [[java.util.stream.Stream Java Stream]] for this array. */ + def parStream: Stream[A] = seqStream.parallel + } + + implicit class ByteArrayHasSeqParStream(a: Array[Byte]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream + } + + implicit class ShortArrayHasSeqParStream(a: Array[Short]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream + } + + implicit class CharArrayHasSeqParStream(a: Array[Char]) { + /** Create a sequential [[java.util.stream.IntStream Java IntStream]] for this array. */ + def seqStream: IntStream = a.stepper.seqStream + /** Create a parallel [[java.util.stream.IntStream Java IntStream]] for this array. */ + def parStream: IntStream = a.stepper.parStream + } + + implicit class FloatArrayHasSeqParStream(a: Array[Float]) { + /** Create a sequential [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def seqStream: DoubleStream = a.stepper.seqStream + + /** Create a parallel [[java.util.stream.DoubleStream Java DoubleStream]] for this array. */ + def parStream: DoubleStream = a.stepper.parStream + } + + // toScala for streams + + implicit class StreamHasToScala[A](stream: Stream[A]) { + def accumulate: AnyAccumulator[A] = toScalaFactory(Accumulator) + + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[scala.jdk.Accumulator]] using `stream.toScalaFactory(Accumulator)` + * builds the result in parallel. + * + * A `toScalaFactory(Accumulator)` call automatically converts streams of boxed integers, longs or + * doubles are converted to the primitive accumulators ([[scala.jdk.IntAccumulator]], etc.). + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + private[java8] def toScalaFactory[C](factory: collection.Factory[A, C])(implicit info: AccumulatorFactoryInfo[A, C]): C = { + def anyAcc = stream.collect(AnyAccumulator.supplier[A], AnyAccumulator.adder[A], AnyAccumulator.merger[A]) + if (info.companion == AnyAccumulator) anyAcc.asInstanceOf[C] + else if (info.companion == IntAccumulator) stream.asInstanceOf[Stream[Int]].collect(IntAccumulator.supplier, IntAccumulator.boxedAdder, IntAccumulator.merger).asInstanceOf[C] + else if (info.companion == LongAccumulator) stream.asInstanceOf[Stream[Long]].collect(LongAccumulator.supplier, LongAccumulator.boxedAdder, LongAccumulator.merger).asInstanceOf[C] + else if (info.companion == DoubleAccumulator) stream.asInstanceOf[Stream[Double]].collect(DoubleAccumulator.supplier, DoubleAccumulator.boxedAdder, DoubleAccumulator.merger).asInstanceOf[C] + else if (stream.isParallel) anyAcc.to(factory) + else factory.fromSpecific(stream.iterator.asScala) + } + + /** + * Copy the elements of this stream into a Scala collection. + * + * For parallel streams, using [[accumulate]] is recommended as it builds the [[scala.jdk.Accumulator]] + * in parallel. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[CC[_]](implicit factory: collection.Factory[A, CC[A]]): CC[A] = { + if (stream.isParallel) toScalaFactory(Accumulator).to(factory) + else factory.fromSpecific(stream.iterator.asScala) + } + + /** Convert a generic Java Stream wrapping a primitive type to a corresponding primitive + * Stream. + */ + def unboxed[S](implicit unboxer: StreamUnboxer[A, S]): S = unboxer(stream) + } + + implicit class StreamIntHasAccumulatePrimitive(s: Stream[Int]) { + def accumulatePrimitive: IntAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class StreamLongHasAccumulatePrimitive(s: Stream[Long]) { + def accumulatePrimitive: LongAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class StreamDoubleHasAccumulatePrimitive(s: Stream[Double]) { + def accumulatePrimitive: DoubleAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class StreamJIntegerHasAccumulatePrimitive(s: Stream[java.lang.Integer]) { + def accumulatePrimitive: IntAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class StreamJLongHasAccumulatePrimitive(s: Stream[java.lang.Long]) { + def accumulatePrimitive: LongAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class StreamJDoubleHasAccumulatePrimitive(s: Stream[java.lang.Double]) { + def accumulatePrimitive: DoubleAccumulator = s.toScalaFactory(Accumulator) + } + + implicit class IntStreamHasToScala(stream: IntStream) { + def accumulate: IntAccumulator = toScalaFactory(IntAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[scala.jdk.Accumulator]] using `stream.toScalaFactory(Accumulator)` + * builds the result in parallel. + * + * A `toScalaFactory(Accumulator)` call automatically converts the `IntStream` to a primitive + * [[scala.jdk.IntAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + private[java8] def toScalaFactory[C](factory: collection.Factory[Int, C])(implicit info: AccumulatorFactoryInfo[Int, C]): C = { + def intAcc = stream.collect(IntAccumulator.supplier, IntAccumulator.adder, IntAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Int], AnyAccumulator.unboxedIntAdder, AnyAccumulator.merger[Int]).asInstanceOf[C] + else if (info.companion == IntAccumulator) intAcc.asInstanceOf[C] + else if (stream.isParallel) intAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Int]].asScala) + } + + /** + * Copy the elements of this stream into a Scala collection. + * + * For parallel streams, using [[accumulate]] is recommended as it builds the [[scala.jdk.IntAccumulator]] + * in parallel. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[CC[_]](implicit factory: collection.Factory[Int, CC[Int]]): CC[Int] = { + if (stream.isParallel) toScalaFactory(IntAccumulator).to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Int]].asScala) + } + } + + implicit class LongStreamHasToScala(stream: LongStream) { + def accumulate: LongAccumulator = toScalaFactory(LongAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[scala.jdk.Accumulator]] using `stream.toScalaFactory(Accumulator)` + * builds the result in parallel. + * + * A `toScalaFactory(Accumulator)` call automatically converts the `LongStream` to a primitive + * [[scala.jdk.LongAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + private[java8] def toScalaFactory[C](factory: collection.Factory[Long, C])(implicit info: AccumulatorFactoryInfo[Long, C]): C = { + def longAcc = stream.collect(LongAccumulator.supplier, LongAccumulator.adder, LongAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Long], AnyAccumulator.unboxedLongAdder, AnyAccumulator.merger[Long]).asInstanceOf[C] + else if (info.companion == LongAccumulator) longAcc.asInstanceOf[C] + else if (stream.isParallel) longAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Long]].asScala) + } + + /** + * Copy the elements of this stream into a Scala collection. + * + * For parallel streams, using [[accumulate]] is recommended as it builds the [[scala.jdk.LongAccumulator]] + * in parallel. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[CC[_]](implicit factory: collection.Factory[Long, CC[Long]]): CC[Long] = { + if (stream.isParallel) toScalaFactory(LongAccumulator).to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Long]].asScala) + } + } + + implicit class DoubleStreamHasToScala(stream: DoubleStream) { + def accumulate: DoubleAccumulator = toScalaFactory(DoubleAccumulator) + + /** + * Copy the elements of this stream into a Scala collection. + * + * Converting a parallel streams to an [[scala.jdk.Accumulator]] using `stream.toScalaFactory(Accumulator)` + * builds the result in parallel. + * + * A `toScalaFactory(Accumulator)` call automatically converts the `DoubleStream` to a primitive + * [[scala.jdk.DoubleAccumulator]]. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + private[java8] def toScalaFactory[C](factory: collection.Factory[Double, C])(implicit info: AccumulatorFactoryInfo[Double, C]): C = { + def doubleAcc = stream.collect(DoubleAccumulator.supplier, DoubleAccumulator.adder, DoubleAccumulator.merger) + if (info.companion == AnyAccumulator) stream.collect(AnyAccumulator.supplier[Double], AnyAccumulator.unboxedDoubleAdder, AnyAccumulator.merger[Double]).asInstanceOf[C] + else if (info.companion == DoubleAccumulator) doubleAcc.asInstanceOf[C] + else if (stream.isParallel) doubleAcc.to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Double]].asScala) + } + + /** + * Copy the elements of this stream into a Scala collection. + * + * For parallel streams, using [[accumulate]] is recommended as it builds the [[scala.jdk.DoubleAccumulator]] + * in parallel. + * + * When converting a parallel stream to a different Scala collection, the stream is first + * converted into an [[scala.jdk.Accumulator]], which supports parallel building. The accumulator is + * then converted to the target collection. Note that the stream is processed eagerly while + * building the accumulator, even if the target collection is lazy. + * + * Sequential streams are directly converted to the target collection. If the target collection + * is lazy, the conversion is lazy as well. + */ + def toScala[CC[_]](implicit factory: collection.Factory[Double, CC[Double]]): CC[Double] = { + if (stream.isParallel) toScalaFactory(DoubleAccumulator).to(factory) + else factory.fromSpecific(stream.iterator.asInstanceOf[java.util.Iterator[Double]].asScala) + } + } +} + +/** `StreamConverters` provides extension methods and other functionality to + * ease interoperability of Scala collections with `java.util.stream` classes. + * + * Scala collections gain extension methods `seqStream` and + * `parStream` that allow them to be used as the source of a `Stream`. + * Some collections either intrinsically cannot be paralellized, or + * could be but an efficient implementation is missing. It this case, + * only `seqStream` is provided. If a collection cannot be stepped over + * at all (e.g. `Traversable`), then it gains neither method. + * + * `Array` also gains `seqStream` and `parStream` methods, and calling those + * on `Array[Double]`, `Array[Int]`, or `Array[Long]` will produce the + * corresponding primitive stream. + * + * Streams gain `accumulate` and `toScala[_]` methods, which collect the stream + * into a custom high-performance `scala.collection.mutable.java8.Accumulator`, + * which is not part of the standard collections hierarchy, or into a named + * Scala collection, respectively. + * + * Generic streams also gain an `unboxed` method that will convert to the + * corresponding unboxed primitive stream, if appropriate. Unboxed streams + * have custom accumulators with improved performance. + * + * Accumulators have `toArray`, `toList`, `iterator`, and `to[_]` methods + * to convert to standard Scala collections. Note that if you wish to + * create an array from a `Stream`, going through an `Accumulator` is + * not the most efficient option: just create the `Array` directly. + * + * Internally, Scala collections implement a hybrid of `Iterator` and + * `java.util.Spliterator` to implement `Stream` compatibility; these + * are called `Stepper`s. In particular, they can test for the presence + * of a next element using `hasStep`, can retrieve the next value with + * `nextStep`, or can optionally retrieve and operate on a value if present + * with `tryStep`, which works like `tryAdvance` in `java.util.Spliterator`. + * + * Every Scala collection that can be stepped + * through has a `stepper` method implicitly provided. In addition, + * maps have `keyStepper` and `valueStepper` methods. A limited number + * of collections operations are defined on `Stepper`s, including conversion + * to Scala collections with `to` or accumulation via `accumulate`. + * `Stepper`s also implement `seqStream` and `parStream` to generate `Stream`s. + * These are provided regardless of whether a `Stepper` can efficiently + * subdivide itself for parallel processing (though one can check for the + * presence of the `EfficientSubstep` trait to know that parallel execution will + * not be limited by long sequential searching steps, and one can call + * `anticipateParallelism` to warn a `Stepper` that it will be used in a parallel + * context and thus may wish to make different tradeoffs). + * + * Examples: + * {{{ + * import scala.compat.java8.StreamConverters._ + * + * val s = Vector(1,2,3,4).parStream // Stream[Int] + * val si = s.unboxed // Stream.OfInt + * val ai = si.accumulate // IntAccumulator + * val v = ai.to[Vector] // Vector[Int] again + * + * val t = Array(2.0, 3.0, 4.0).parStream // DoubleStream + * val q = t.toScala[scala.collection.immutable.Queue] // Queue[Double] + * + * val x = List(1L, 2L, 3L, 4L).stepper.parStream.sum // 10, potentially computed in parallel + * }}} + */ +object StreamConverters +extends StreamExtensions +with converterImpl.Priority1AccumulatorConverters +{ + implicit def richIntStepper(s: Stepper[Int]): StepperExtensions[Int] = new StepperExtensions[Int](s) + implicit def richLongStepper(s: Stepper[Long]): StepperExtensions[Long] = new StepperExtensions[Long](s) + implicit def richDoubleStepper(s: Stepper[Double]): StepperExtensions[Double] = new StepperExtensions[Double](s) +} diff --git a/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala new file mode 100644 index 0000000..ab5cfca --- /dev/null +++ b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala @@ -0,0 +1,30 @@ +package scala.compat.java8 + +package object collectionImpl { + type Accumulator[A] = scala.jdk.AnyAccumulator[A] + val Accumulator = scala.jdk.AnyAccumulator + + type IntAccumulator = scala.jdk.IntAccumulator + val IntAccumulator = scala.jdk.IntAccumulator + + type LongAccumulator = scala.jdk.LongAccumulator + val LongAccumulator = scala.jdk.LongAccumulator + + type DoubleAccumulator = scala.jdk.DoubleAccumulator + val DoubleAccumulator = scala.jdk.DoubleAccumulator + + type Stepper[A] = scala.collection.Stepper[A] + val Stepper = scala.collection.Stepper + + type AnyStepper[A] = scala.collection.AnyStepper[A] + val AnyStepper = scala.collection.AnyStepper + + type IntStepper = scala.collection.IntStepper + val IntStepper = scala.collection.IntStepper + + type LongStepper = scala.collection.LongStepper + val LongStepper = scala.collection.LongStepper + + type DoubleStepper = scala.collection.DoubleStepper + val DoubleStepper = scala.collection.DoubleStepper +} diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala new file mode 100644 index 0000000..fa28114 --- /dev/null +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala @@ -0,0 +1,47 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8.converterImpl + +import scala.compat.java8.collectionImpl._ + +final class CollectionCanAccumulate[A](private val underlying: IterableOnce[A]) extends AnyVal { + def accumulate: Accumulator[A] = underlying.iterator.to(Accumulator) +} + +final class AccumulateDoubleCollection(private val underlying: IterableOnce[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = underlying.iterator.to(DoubleAccumulator) +} + +final class AccumulateIntCollection(private val underlying: IterableOnce[Int]) extends AnyVal { + def accumulate: IntAccumulator = underlying.iterator.to(IntAccumulator) +} + +final class AccumulateLongCollection(private val underlying: IterableOnce[Long]) extends AnyVal { + def accumulate: LongAccumulator = underlying.iterator.to(LongAccumulator) +} + +final class AccumulateAnyArray[A](private val underlying: Array[A]) extends AnyVal { + def accumulate: Accumulator[A] = underlying.to(Accumulator) +} + +final class AccumulateDoubleArray(private val underlying: Array[Double]) extends AnyVal { + def accumulate: DoubleAccumulator = underlying.to(DoubleAccumulator) +} + +final class AccumulateIntArray(private val underlying: Array[Int]) extends AnyVal { + def accumulate: IntAccumulator = underlying.to(IntAccumulator) +} + +final class AccumulateLongArray(private val underlying: Array[Long]) extends AnyVal { + def accumulate: LongAccumulator = underlying.to(LongAccumulator) +} diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala new file mode 100644 index 0000000..4ff943a --- /dev/null +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -0,0 +1,32 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8.converterImpl + +import scala.language.implicitConversions + +trait Priority3AccumulatorConverters { + implicit def collectionCanAccumulate[A](underlying: IterableOnce[A]) = new CollectionCanAccumulate[A](underlying) +} + +trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { + implicit def accumulateDoubleCollection(underlying: IterableOnce[Double]) = new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: IterableOnce[Int]) = new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: IterableOnce[Long]) = new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) +} + +trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { + implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) +} diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala new file mode 100644 index 0000000..15f384a --- /dev/null +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala @@ -0,0 +1,77 @@ +package scala.compat.java8.converterImpl + +import scala.collection.convert.StreamExtensions.AccumulatorFactoryInfo +import scala.compat.java8.collectionImpl.{DoubleAccumulator, IntAccumulator, LongAccumulator, Stepper} +import scala.jdk.AnyAccumulator + +class StepperExtensions[@specialized(Double, Int, Long) A](private val s: Stepper[A]) { + def accumulate[C](implicit info: AccumulatorFactoryInfo[A, C]): C = { + info.companion match { + case IntAccumulator => + val a = new IntAccumulator() + val is = s.asInstanceOf[Stepper[Int]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case LongAccumulator => + val a = new LongAccumulator() + val is = s.asInstanceOf[Stepper[Long]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case DoubleAccumulator => + val a = new DoubleAccumulator() + val is = s.asInstanceOf[Stepper[Double]] + while (is.hasStep) a += is.nextStep() + a.asInstanceOf[C] + case AnyAccumulator | null => + val a = new AnyAccumulator[A] + while (s.hasStep) a += s.nextStep() + a.asInstanceOf[C] + } + } + + def substep(): Stepper[A] = s.trySplit() + + /** Consumes all remaining elements in this `Stepper` and counts how many there are. + * This is a terminal operation. + */ + def count(): Long = { var n = 0L; while (s.hasStep) { s.nextStep(); n += 1 }; n } + + /** Consumes all remaining elements in this `Stepper` and counts how many satisfy condition `p`. + * This is a terminal operation. + */ + def count(p: A => Boolean): Long = { var n = 0L; while (s.hasStep) { if (p(s.nextStep())) n += 1 }; n } + + /** Searches for an element that satisfies condition `p`. If none are found, it returns `false`. + * This is a terminal operation. + */ + def exists(p: A => Boolean): Boolean = { while(s.hasStep) { if (p(s.nextStep())) return true }; false } + + /** Searches for an element that satisifes condition `p`, returning it wrapped in `Some` if one is found, or `None` otherwise. + * This is a terminal operation. + */ + def find(p: A => Boolean): Option[A] = { while (s.hasStep) { val a = s.nextStep(); if (p(a)) return Some(a) }; None } + + /** Repeatedly applies `op` to propagate an initial value `zero` through all elements of the collection. + * Traversal order is left-to-right. + * This is a terminal operation. + */ + def fold[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B) = { var b = zero; while (s.hasStep) { b = op(b, s.nextStep()) }; b } + + /** Repeatedly applies `op` to propagate an initial value `zero` through the collection until a condition `p` is met. + * If `p` is never met, the result of the last operation is returned. + * This is a terminal operation. + */ + def foldTo[@specialized(Double, Int, Long) B](zero: B)(op: (B, A) => B)(p: B => Boolean) = { var b = zero; while (!p(b) && s.hasStep) { b = op(b, s.nextStep()) }; b } + + /** Applies `f` to every remaining element in the collection. + * This is a terminal operation. + */ + def foreach(f: A => Unit): Unit = { while (s.hasStep) f(s.nextStep()) } + + /** Repeatedly merges elements with `op` until only a single element remains. + * Throws an exception if the `Stepper` is empty. + * Merging occurs from left to right. + * This is a terminal operation. + */ + def reduce(op: (A, A) => A): A = { var a = s.nextStep(); while (s.hasStep) { a = op(a, s.nextStep()) }; a } +} diff --git a/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala new file mode 100644 index 0000000..ea4cf4d --- /dev/null +++ b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -0,0 +1,8 @@ +package scala.concurrent.java8 + +import scala.concurrent.ExecutionContext + +// TODO: make this private[scala] when genjavadoc allows for that. +object FuturesConvertersImplCompat { + def InternalCallbackExecutor = ExecutionContext.parasitic +} diff --git a/src/main/scala/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala similarity index 100% rename from src/main/scala/scala/compat/java8/SpliteratorConverters.scala rename to src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala diff --git a/src/main/scala/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala similarity index 100% rename from src/main/scala/scala/compat/java8/StreamConverters.scala rename to src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/Accumulator.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/AccumulatorLike.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/DoubleAccumulator.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/IntAccumulator.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/LongAccumulator.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala diff --git a/src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala similarity index 100% rename from src/main/scala/scala/compat/java8/collectionImpl/Stepper.scala rename to src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/Accumulates.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/AccumulatorConverters.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/MakesSteppers.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepConverters.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsArray.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsBitSet.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsFlatHashTable.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsHashTable.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsImmHashMap.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsImmHashSet.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsIndexedSeq.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsIterable.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsIterator.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeGapped.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeIndexed.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeIterator.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeSliced.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsLinearSeq.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsMap.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsRange.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsString.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsVector.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala diff --git a/src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala similarity index 100% rename from src/main/scala/scala/compat/java8/converterImpl/StepsWithTail.scala rename to src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala diff --git a/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala new file mode 100644 index 0000000..4262f7a --- /dev/null +++ b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -0,0 +1,8 @@ +package scala.concurrent.java8 + +import scala.concurrent.Future + +// TODO: make this private[scala] when genjavadoc allows for that. +object FuturesConvertersImplCompat { + def InternalCallbackExecutor = Future.InternalCallbackExecutor +} diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 341f400..794ae7e 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -15,6 +15,7 @@ package scala.compat.java8 import scala.language.implicitConversions import scala.concurrent.java8.FuturesConvertersImpl._ +import scala.concurrent.java8.FuturesConvertersImplCompat._ import scala.concurrent.{ Future, Promise, ExecutionContext, ExecutionContextExecutorService, ExecutionContextExecutor } import java.util.concurrent.{ CompletionStage, Executor, ExecutorService } import java.util.function.Consumer diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 2d80ba6..d0abb4d 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -53,10 +53,10 @@ object PrimitiveIteratorConverters { def nextDouble() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } @@ -74,10 +74,10 @@ object PrimitiveIteratorConverters { def nextInt() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } @@ -95,10 +95,10 @@ object PrimitiveIteratorConverters { def nextLong() = it.next() override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { - while (it.hasNext) c.accept(it.next) + while (it.hasNext) c.accept(it.next()) } } } diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 31a6523..3099d6e 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -14,20 +14,19 @@ package scala.concurrent.java8 // Located in this package to access private[concurrent] members -import scala.concurrent.{ Future, ExecutionContext } import java.util.concurrent._ +import java.util.function.{BiConsumer, BiFunction, Consumer, Function => JF} + +import scala.concurrent.Future import scala.concurrent.impl.Promise.DefaultPromise -import scala.util.{ Try, Success, Failure } -import java.util.function.{ BiConsumer, Function ⇒ JF, Consumer, BiFunction } +import scala.util.{Failure, Success, Try} // TODO: make this private[scala] when genjavadoc allows for that. object FuturesConvertersImpl { - def InternalCallbackExecutor = Future.InternalCallbackExecutor - class CF[T](val wrapped: Future[T]) extends CompletableFuture[T] with (Try[T] => Unit) { override def apply(t: Try[T]): Unit = t match { - case Success(v) ⇒ complete(v) - case Failure(e) ⇒ completeExceptionally(e) + case Success(v) => complete(v) + case Failure(e) => completeExceptionally(e) } /* @@ -67,7 +66,7 @@ object FuturesConvertersImpl { try { fn(e).asInstanceOf[AnyRef] } catch { - case thr: Throwable ⇒ cf.completeExceptionally(thr); this + case thr: Throwable => cf.completeExceptionally(thr); this } if (n ne this) cf.complete(n.asInstanceOf[T]) } diff --git a/src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java b/src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java similarity index 100% rename from src/test/java/scala/compat/java8/runtime/LambdaDeserializerTest.java rename to src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java diff --git a/src/test/java/scala/compat/java8/BoxingTest.java b/src/test/java/scala/compat/java8/BoxingTest.java index e0a2c03..7f798ff 100644 --- a/src/test/java/scala/compat/java8/BoxingTest.java +++ b/src/test/java/scala/compat/java8/BoxingTest.java @@ -18,24 +18,26 @@ public class BoxingTest { @Test public void nullBoxesInterpretedAsZeroF1() { - scala.Function1 jFunction1 = new JFunction1$mcII$sp() { + Object o = new JFunction1$mcII$sp() { @Override public int apply$mcII$sp(int v1) { return v1 + 1; } }; + scala.Function1 jFunction1 = (scala.Function1)o; Integer result = (Integer) jFunction1.apply(null); assert (result.intValue() == 1); } @Test public void nullBoxesInterpretedAsZeroF2() { - scala.Function2 jFunction2 = new JFunction2$mcIII$sp() { + Object o = new JFunction2$mcIII$sp() { @Override public int apply$mcIII$sp(int v1, int v2) { return v1 + v2 + 1; } }; + scala.Function2 jFunction2 = (scala.Function2)o; Integer result = (Integer) jFunction2.apply(null, null); assert (result.intValue() == 1); } diff --git a/src/test/scala-2.13+/scala/compat/java8/StepConvertersTest.scala b/src/test/scala-2.13+/scala/compat/java8/StepConvertersTest.scala new file mode 100644 index 0000000..667e13c --- /dev/null +++ b/src/test/scala-2.13+/scala/compat/java8/StepConvertersTest.scala @@ -0,0 +1,565 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8 + +import org.junit.Test +import org.junit.Assert._ + +class StepConvertersTest { + import collectionImpl._ + import converterImpl._ + import StreamConverters._ // Includes StepConverters! + import scala.{ collection => co } + import collection.{ mutable => cm, immutable => ci, concurrent => cc } + + def isAcc[X](x: X): Boolean = x.getClass.getSimpleName.contains("AccumulatorStepper") + + trait SpecCheck { + def check[X](x: X): Boolean + def msg[X](x: X): String + def assert(x: Any): Unit = + if(!check(x)) assertTrue(msg(x), false) + } + object SpecCheck { + def apply(f: Any => Boolean, err: Any => String = (_ => "SpecCheck failed")) = new SpecCheck { + def check[X](x: X): Boolean = f(x) + def msg[X](x: X): String = err(x) + } + } + + def _eh_[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + } + + def IFFY[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(isAcc(x)) + } + + def Okay[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) + } + + def Fine[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) + } + + def good[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + assertTrue(!isAcc(x)) + } + + def Tell[X](x: => X)(implicit correctSpec: SpecCheck): Unit = { + println(x.getClass.getName + " -> " + isAcc(x)) + assertTrue(x.isInstanceOf[Stepper[_]]) + correctSpec.assert(x) + } + + @Test + def comprehensivelyGeneric(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[AnyStepper[_]]) + + // Collection section + Okay( co.Iterator[String]("salmon").buffered.stepper ) + good( co.IndexedSeq[String]("salmon").stepper ) + Okay( co.Iterable[String]("salmon").stepper ) + Okay( co.Iterable[String]("salmon").view.stepper ) + Okay( co.Iterator[String]("salmon").stepper ) + Okay( co.LinearSeq[String]("salmon").stepper ) + Okay( co.Map[String, String]("fish" -> "salmon").stepper ) + Okay( co.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.Seq[String]("salmon").stepper ) + Okay( co.Seq[String]("salmon").view.stepper ) + Okay( co.Set[String]("salmon").stepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( co.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( co.SortedSet[String]("salmon").stepper ) + IFFY( co.Iterable[String]("salmon").accumulate.stepper ) + IFFY( (co.Iterator[String]("salmon"): co.IterableOnce[String]).accumulate.stepper ) + IFFY( co.Iterable[String]("salmon").view.accumulate.stepper ) + + // Immutable section + Okay( ci.::("salmon", Nil).stepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).stepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).keyStepper ) + Okay( (ci.HashMap[String, String]("fish" -> "salmon"): ci.AbstractMap[String, String]).valueStepper ) + good( ci.HashSet[String]("salmon").stepper ) + good( ci.IndexedSeq[String]("salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").valueStepper ) + Okay( ci.Iterable[String]("salmon").stepper ) + Okay( ci.LinearSeq[String]("salmon").stepper ) + Okay( ci.List[String]("salmon").stepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.ListMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.ListSet[String]("salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").stepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.Queue[String]("salmon").stepper ) + Okay( ci.Seq[String]("salmon").stepper ) + Okay( ci.Set[String]("salmon").stepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.SortedMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.SortedSet[String]("salmon").stepper ) + Okay( ci.Stream[String]("salmon").stepper ) + _eh_( ci.Stream[String]("salmon").view.stepper ) + Okay( ci.LazyList[String]("salmon").stepper ) + _eh_( ci.LazyList[String]("salmon").view.stepper ) + IFFY( ci.Iterable[String]("salmon").accumulate.stepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").stepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( ci.TreeMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( ci.TreeSet[String]("salmon").stepper ) + good( ci.Vector[String]("salmon").stepper ) + + // Mutable section + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractBuffer[String]).stepper ) + Okay( (cm.PriorityQueue[String]("salmon"): cm.AbstractIterable[String]).stepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).stepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).keyStepper ) + Okay( (cm.HashMap[String, String]("fish" -> "salmon"): cm.AbstractMap[String, String]).valueStepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.AbstractSeq[String]).stepper ) + Okay( (cm.HashSet[String]("salmon"): cm.AbstractSet[String]).stepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").stepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").keyStepper ) + Okay( cm.AnyRefMap[String,String]("fish" -> "salmon").valueStepper ) + good( cm.ArrayBuffer[String]("salmon").stepper ) + good( (Array("salmon"): cm.ArraySeq[String]).stepper ) + good( cm.ArraySeq[String]("salmon").stepper ) + _eh_( cm.ArrayStack[String]("salmon").stepper ) + Okay( (cm.ArrayBuffer[String]("salmon"): cm.Buffer[String]).stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.HashMap[String, String]("fish" -> "salmon").valueStepper ) + good( cm.HashSet[String]("salmon").stepper ) + good( cm.IndexedSeq[String]("salmon").stepper ) + good( cm.IndexedSeq[String]("salmon").view.stepper ) + Okay( cm.Iterable[String]("salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").stepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").keyStepper ) + good( cm.LinkedHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.LinkedHashSet[String]("salmon").stepper ) + Okay( cm.ListBuffer[String]("salmon").stepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.ListMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").stepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").valueStepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").stepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.Map[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.OpenHashMap[String, String]("fish" -> "salmon").valueStepper ) + Okay( cm.PriorityQueue[String]("salmon").stepper ) + Fine( cm.Queue[String]("salmon").stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` + Okay( cm.Seq[String]("salmon").stepper ) + Okay( cm.Set[String]("salmon").stepper ) + Okay( cm.SortedSet[String]("salmon").stepper ) + Fine( cm.Stack[String]("salmon").stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[String]("salmon").accumulate.stepper ) + Okay( cm.TreeSet[String]("salmon").stepper ) + Okay( cm.UnrolledBuffer[String]("salmon").stepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").stepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cm.WeakHashMap[String, String]("fish" -> "salmon").valueStepper ) + + // Java 6 converters section + + // Concurrent section + Okay( cc.TrieMap[String, String]("fish" -> "salmon").stepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( cc.TrieMap[String, String]("fish" -> "salmon").keyStepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).stepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).keyStepper ) + Okay( (cc.TrieMap[String, String]("fish" -> "salmon"): cc.Map[String, String]).valueStepper ) + } + + @Test + def comprehensivelyDouble(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[DoubleStepper]) + //Double-specific tests + + // Collection section + Okay( co.Iterator[Double](3.14159).buffered.stepper ) + good( co.IndexedSeq[Double](3.14159).stepper ) + Okay( co.Iterable[Double](3.14159).stepper ) + Okay( co.Iterable[Double](3.14159).view.stepper ) + Okay( co.Iterator[Double](3.14159).stepper ) + Okay( co.LinearSeq[Double](3.14159).stepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.Seq[Double](3.14159).stepper ) + Okay( co.Seq[Double](3.14159).view.stepper ) + Okay( co.Set[Double](3.14159).stepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( co.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( co.SortedSet[Double](3.14159).stepper ) + IFFY( co.Iterable[Double](3.14159).accumulate.stepper ) + IFFY( (co.Iterator[Double](3.14159): co.IterableOnce[Double]).accumulate.stepper ) + IFFY( co.Iterable[Double](3.14159).view.accumulate.stepper ) + + // Immutable section + Okay( ci.::(3.14159, Nil).stepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).keyStepper ) + Okay( (ci.HashMap[Double, Double](2.718281828 -> 3.14159): ci.AbstractMap[Double, Double]).valueStepper ) + good( ci.HashSet[Double](3.14159).stepper ) + good( ci.IndexedSeq[Double](3.14159).stepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).valueStepper ) + Okay( ci.Iterable[Double](3.14159).stepper ) + Okay( ci.LinearSeq[Double](3.14159).stepper ) + Okay( ci.List[Double](3.14159).stepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.ListSet[Double](3.14159).stepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.Queue[Double](3.14159).stepper ) + Okay( ci.Seq[Double](3.14159).stepper ) + Okay( ci.Set[Double](3.14159).stepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.SortedMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.SortedSet[Double](3.14159).stepper ) + Okay( ci.Stream[Double](3.14159).stepper ) + _eh_( ci.Stream[Double](3.14159).view.stepper ) + Okay( ci.LazyList[Double](3.14159).stepper ) + _eh_( ci.LazyList[Double](3.14159).view.stepper ) + IFFY( ci.Iterable[Double](3.14159).accumulate.stepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( ci.TreeMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( ci.TreeSet[Double](3.14159).stepper ) + good( ci.Vector[Double](3.14159).stepper ) + + // Mutable section + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractBuffer[Double]).stepper ) + Okay( (cm.PriorityQueue[Double](3.14159): cm.AbstractIterable[Double]).stepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).keyStepper ) + Okay( (cm.HashMap[Double, Double](2.718281828 -> 3.14159): cm.AbstractMap[Double, Double]).valueStepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.AbstractSeq[Double]).stepper ) + Okay( (cm.HashSet[Double](3.14159): cm.AbstractSet[Double]).stepper ) + Okay( cm.AnyRefMap[String,Double]("fish" -> 3.14159).valueStepper ) + good( cm.ArrayBuffer[Double](3.14159).stepper ) + good( (Array(3.14159): cm.ArraySeq[Double]).stepper ) + good( cm.ArraySeq[Double](3.14159).stepper ) + _eh_( cm.ArrayStack[Double](3.14159).stepper ) + Okay( (cm.ArrayBuffer[Double](3.14159): cm.Buffer[Double]).stepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.HashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + good( cm.HashSet[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).stepper ) + good( cm.IndexedSeq[Double](3.14159).view.stepper ) + Okay( cm.Iterable[Double](3.14159).stepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + good( cm.LinkedHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LinkedHashSet[Double](3.14159).stepper ) + Okay( cm.ListBuffer[Double](3.14159).stepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.ListMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).valueStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.Map[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.OpenHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( cm.PriorityQueue[Double](3.14159).stepper ) + Fine( cm.Queue[Double](3.14159).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` + Okay( cm.Seq[Double](3.14159).stepper ) + Okay( cm.Set[Double](3.14159).stepper ) + Okay( cm.SortedSet[Double](3.14159).stepper ) + Fine( cm.Stack[Double](3.14159).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Double](3.14159).accumulate.stepper ) + Okay( cm.TreeSet[Double](3.14159).stepper ) + Okay( cm.UnrolledBuffer[Double](3.14159).stepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cm.WeakHashMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + + // Java 6 converters section + + // Concurrent section + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).keyStepper ) + Okay( cc.TrieMap[Double, Double](2.718281828 -> 3.14159).valueStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).keyStepper ) + Okay( (cc.TrieMap[Double, Double](2.718281828 -> 3.14159): cc.Map[Double, Double]).valueStepper ) + } + + @Test + def comprehensivelyInt(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") + + // Int-specific tests + good( co.BitSet(42).stepper ) + good( ci.BitSet(42).stepper ) + good( ci.NumericRange(123456, 123458, 1).stepper ) + good( cm.BitSet(42).stepper ) + good( (1 until 2).stepper ) + Okay( ci.IntMap[String](123456 -> "salmon").keyStepper ) + Okay( ci.IntMap[Double](123456 -> 3.14159).keyStepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).keyStepper ) + + // Collection section + Okay( co.Iterator[Int](654321).buffered.stepper ) + good( co.IndexedSeq[Int](654321).stepper ) + Okay( co.Iterable[Int](654321).stepper ) + Okay( co.Iterable[Int](654321).view.stepper ) + Okay( co.Iterator[Int](654321).stepper ) + Okay( co.LinearSeq[Int](654321).stepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.Seq[Int](654321).stepper ) + Okay( co.Seq[Int](654321).view.stepper ) + Okay( co.Set[Int](654321).stepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( co.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( co.SortedSet[Int](654321).stepper ) + IFFY( co.Iterable[Int](654321).accumulate.stepper ) + IFFY( (co.Iterator[Int](654321): co.IterableOnce[Int]).accumulate.stepper ) + IFFY( co.Iterable[Int](654321).view.accumulate.stepper ) + + // Immutable section + Okay( ci.::(654321, Nil).stepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).keyStepper ) + Okay( (ci.HashMap[Int, Int](0xDEEDED -> 654321): ci.AbstractMap[Int, Int]).valueStepper ) + good( ci.HashSet[Int](654321).stepper ) + good( ci.IndexedSeq[Int](654321).stepper ) + Okay( ci.IntMap[Int](123456 -> 654321).keyStepper ) + Okay( ci.IntMap[Int](123456 -> 654321).valueStepper ) + Okay( ci.Iterable[Int](654321).stepper ) + Okay( ci.LinearSeq[Int](654321).stepper ) + Okay( ci.List[Int](654321).stepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.ListSet[Int](654321).stepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.Queue[Int](654321).stepper ) + Okay( ci.Seq[Int](654321).stepper ) + Okay( ci.Set[Int](654321).stepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.SortedMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.SortedSet[Int](654321).stepper ) + Okay( ci.Stream[Int](654321).stepper ) + _eh_( ci.Stream[Int](654321).view.stepper ) + Okay( ci.LazyList[Int](654321).stepper ) + _eh_( ci.LazyList[Int](654321).view.stepper ) + IFFY( ci.Iterable[Int](654321).accumulate.stepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( ci.TreeMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( ci.TreeSet[Int](654321).stepper ) + good( ci.Vector[Int](654321).stepper ) + + // Mutable section + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractBuffer[Int]).stepper ) + Okay( (cm.PriorityQueue[Int](654321): cm.AbstractIterable[Int]).stepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).keyStepper ) + Okay( (cm.HashMap[Int, Int](0xDEEDED -> 654321): cm.AbstractMap[Int, Int]).valueStepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.AbstractSeq[Int]).stepper ) + Okay( (cm.HashSet[Int](654321): cm.AbstractSet[Int]).stepper ) + Okay( cm.AnyRefMap[String, Int]("fish" -> 654321).valueStepper ) + good( cm.ArrayBuffer[Int](654321).stepper ) + good( (Array(654321): cm.ArraySeq[Int]).stepper ) + good( cm.ArraySeq[Int](654321).stepper ) + _eh_( cm.ArrayStack[Int](654321).stepper ) + Okay( (cm.ArrayBuffer[Int](654321): cm.Buffer[Int]).stepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.HashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + good( cm.HashSet[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).stepper ) + good( cm.IndexedSeq[Int](654321).view.stepper ) + Okay( cm.Iterable[Int](654321).stepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + good( cm.LinkedHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LinkedHashSet[Int](654321).stepper ) + Okay( cm.ListBuffer[Int](654321).stepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.ListMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).valueStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.Map[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.OpenHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( cm.PriorityQueue[Int](654321).stepper ) + Fine( cm.Queue[Int](654321).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` + Okay( cm.Seq[Int](654321).stepper ) + Okay( cm.Set[Int](654321).stepper ) + Okay( cm.SortedSet[Int](654321).stepper ) + Fine( cm.Stack[Int](654321).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Int](654321).accumulate.stepper ) + Okay( cm.TreeSet[Int](654321).stepper ) + Okay( cm.UnrolledBuffer[Int](654321).stepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cm.WeakHashMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + + // Java 6 converters section + + // Concurrent section + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).keyStepper ) + Okay( cc.TrieMap[Int, Int](0xDEEDED -> 654321).valueStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).keyStepper ) + Okay( (cc.TrieMap[Int, Int](0xDEEDED -> 654321): cc.Map[Int, Int]).valueStepper ) + } + + @Test + def shortWidening(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") + + good( Array[Short](654321.toShort).stepper ) + good( (Array[Short](654321.toShort): cm.ArraySeq[Short]).stepper ) + + //TODO: None of these currently work because there are no native Stepper implementations: + + //good( ci.NumericRange(123456.toShort, 123458.toShort, 1.toShort).stepper ) + //good( ((Array[Short](654321.toShort): cm.ArraySeq[Short]): cm.ArrayLike[Short, cm.ArraySeq[Short]]).stepper ) + //good( (Array[Short](654321.toShort): cm.ArrayOps[Short]).stepper ) + //good( cm.ResizableArray[Short](654321.toShort).stepper ) + } + + @Test + def comprehensivelyLong(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[LongStepper]) + + // Long-specific tests + good( ci.NumericRange(9876543210L, 9876543212L, 1L).stepper ) + Okay( ci.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( cm.LongMap[String](9876543210L -> "salmon").keyStepper ) + Okay( ci.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( cm.LongMap[Double](9876543210L -> 3.14159).keyStepper ) + Okay( ci.LongMap[Int](9876543210L -> 654321).keyStepper ) + Okay( cm.LongMap[Int](9876543210L -> 654321).keyStepper ) + + // Collection section + Okay( co.Iterator[Long](0x123456789L).buffered.stepper ) + good( co.IndexedSeq[Long](0x123456789L).stepper ) + Okay( co.Iterable[Long](0x123456789L).stepper ) + Okay( co.Iterable[Long](0x123456789L).view.stepper ) + Okay( co.Iterator[Long](0x123456789L).stepper ) + Okay( co.LinearSeq[Long](0x123456789L).stepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.Seq[Long](0x123456789L).stepper ) + Okay( co.Seq[Long](0x123456789L).view.stepper ) + Okay( co.Set[Long](0x123456789L).stepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( co.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( co.SortedSet[Long](0x123456789L).stepper ) + IFFY( co.Iterable[Long](0x123456789L).accumulate.stepper ) + IFFY( (co.Iterator[Long](0x123456789L): co.IterableOnce[Long]).accumulate.stepper ) + IFFY( co.Iterable[Long](0x123456789L).view.accumulate.stepper ) + + // Immutable section + Okay( ci.::(0x123456789L, Nil).stepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).keyStepper ) + Okay( (ci.HashMap[Long, Long](1234567654321L -> 0x123456789L): ci.AbstractMap[Long, Long]).valueStepper ) + good( ci.HashSet[Long](0x123456789L).stepper ) + good( ci.IndexedSeq[Long](0x123456789L).stepper ) + Okay( ci.IntMap[Long](123456 -> 0x123456789L).valueStepper ) + Okay( ci.Iterable[Long](0x123456789L).stepper ) + Okay( ci.LinearSeq[Long](0x123456789L).stepper ) + Okay( ci.List[Long](0x123456789L).stepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.ListSet[Long](0x123456789L).stepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( ci.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.Queue[Long](0x123456789L).stepper ) + Okay( ci.Seq[Long](0x123456789L).stepper ) + Okay( ci.Set[Long](0x123456789L).stepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.SortedMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.SortedSet[Long](0x123456789L).stepper ) + Okay( ci.Stream[Long](0x123456789L).stepper ) + _eh_( ci.Stream[Long](0x123456789L).view.stepper ) + Okay( ci.LazyList[Long](0x123456789L).stepper ) + _eh_( ci.LazyList[Long](0x123456789L).view.stepper ) + IFFY( ci.Iterable[Long](0x123456789L).accumulate.stepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( ci.TreeMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( ci.TreeSet[Long](0x123456789L).stepper ) + good( ci.Vector[Long](0x123456789L).stepper ) + + // Mutable section + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractBuffer[Long]).stepper ) + Okay( (cm.PriorityQueue[Long](0x123456789L): cm.AbstractIterable[Long]).stepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).keyStepper ) + Okay( (cm.HashMap[Long, Long](1234567654321L -> 0x123456789L): cm.AbstractMap[Long, Long]).valueStepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.AbstractSeq[Long]).stepper ) + Okay( (cm.HashSet[Long](0x123456789L): cm.AbstractSet[Long]).stepper ) + Okay( cm.AnyRefMap[String,Long]("fish" -> 0x123456789L).valueStepper ) + good( cm.ArrayBuffer[Long](0x123456789L).stepper ) + good( (Array(0x123456789L): cm.ArraySeq[Long]).stepper ) + good( cm.ArraySeq[Long](0x123456789L).stepper ) + _eh_( cm.ArrayStack[Long](0x123456789L).stepper ) + Okay( (cm.ArrayBuffer[Long](0x123456789L): cm.Buffer[Long]).stepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.HashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + good( cm.HashSet[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).stepper ) + good( cm.IndexedSeq[Long](0x123456789L).view.stepper ) + Okay( cm.Iterable[Long](0x123456789L).stepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + good( cm.LinkedHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LinkedHashSet[Long](0x123456789L).stepper ) + Okay( cm.ListBuffer[Long](0x123456789L).stepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.ListMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).keyStepper ) + Okay( cm.LongMap[Long](9876543210L -> 0x123456789L).valueStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.Map[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.OpenHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( cm.PriorityQueue[Long](0x123456789L).stepper ) + Fine( cm.Queue[Long](0x123456789L).stepper ) // Used to be `Good` in 2.12, in 2.13 `Queue` is no longer a `LinearSeq` + Okay( cm.Seq[Long](0x123456789L).stepper ) + Okay( cm.Set[Long](0x123456789L).stepper ) + Okay( cm.SortedSet[Long](0x123456789L).stepper ) + Fine( cm.Stack[Long](0x123456789L).stepper ) // Used to be `Good` in 2.12, in 2.13 `Stack` is no longer a `LinearSeq` + IFFY( cm.Iterable[Long](0x123456789L).accumulate.stepper ) + Okay( cm.TreeSet[Long](0x123456789L).stepper ) + Okay( cm.UnrolledBuffer[Long](0x123456789L).stepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cm.WeakHashMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + + // Java 6 converters section + + // Concurrent section + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).keyStepper ) + Okay( cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L).valueStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).keyStepper ) + Okay( (cc.TrieMap[Long, Long](1234567654321L -> 0x123456789L): cc.Map[Long, Long]).valueStepper ) + } + + @Test + def comprehensivelySpecific(): Unit = { + implicit val spec = SpecCheck(_.isInstanceOf[IntStepper], x => s"$x should be an IntStepper") + + good( ci.NumericRange(277: Short, 279: Short, 1: Short).stepper ) + good( ("salmon": ci.WrappedString).stepper ) + } +} diff --git a/src/test/scala-2.13+/scala/compat/java8/StepperTest.scala b/src/test/scala-2.13+/scala/compat/java8/StepperTest.scala new file mode 100644 index 0000000..e8e51ec --- /dev/null +++ b/src/test/scala-2.13+/scala/compat/java8/StepperTest.scala @@ -0,0 +1,319 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8 + +import java.util + +import org.junit.Test +import org.junit.Assert._ +import java.util.Spliterator + +import collectionImpl._ +import StreamConverters._ +import scala.collection.{AnyStepper, IntStepper} + + +class IncStepperA(private val size0: Long) extends IntStepper { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED + override def estimateSize: Long = math.max(0L, size0 - i) + def hasStep = i < size0 + def nextStep() = { i += 1; (i - 1).toInt } + def trySplit() = if (estimateSize <= 1) null else { + val sub = new IncStepperA(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } +} + +class IncSpliterator(private val size0: Long) extends Spliterator.OfInt { + if (size0 < 0) throw new IllegalArgumentException("Size must be >= 0L") + private var i = 0L + def characteristics = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED + def estimateSize() = math.max(0L, size0 - i) + def tryAdvance(f: java.util.function.IntConsumer): Boolean = if (i >= size0) false else { f.accept(i.toInt); i += 1; true } + def trySplit(): Spliterator.OfInt = if (i+1 >= size0) null else { + val sub = new IncSpliterator(size0 - (size0 - i)/2) + sub.i = i + i = sub.size0 + sub + } + override def forEachRemaining(f: java.util.function.IntConsumer): Unit = { while (i < size0) { f.accept(i.toInt); i += 1 } } +} + +class MappingStepper[@specialized (Double, Int, Long) A, @specialized(Double, Int, Long) B](underlying: Stepper[A], mapping: A => B) extends Stepper[B] { + def characteristics = underlying.characteristics + def hasStep = underlying.hasStep + def nextStep() = mapping(underlying.nextStep()) + + override def trySplit(): Stepper[B] = { + val r = underlying.trySplit() + if (r == null) null else new MappingStepper[A, B](r, mapping) + } + + override def estimateSize: Long = underlying.estimateSize + + override def javaIterator[C >: B]: util.Iterator[_] = new util.Iterator[B] { + override def hasNext: Boolean = underlying.hasStep + override def next(): B = mapping(underlying.nextStep()) + } + def substep() = { + val undersub = underlying.substep() + if (undersub == null) null + else new MappingStepper(undersub, mapping) + } + def spliterator[C >: B]: Spliterator[_] = new MappingSpliterator[A, B](underlying.spliterator.asInstanceOf[Spliterator[A]], mapping) +} + +class MappingSpliterator[A, B](private val underlying: Spliterator[A], mapping: A => B) extends Spliterator[B] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: B]): Boolean = underlying.tryAdvance(new java.util.function.Consumer[A]{ def accept(a: A): Unit = { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[B] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new MappingSpliterator(undersplit, mapping) + } +} +class IntToGenericSpliterator[A](private val underlying: Spliterator.OfInt, mapping: Int => A) extends Spliterator[A] { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.Consumer[_ >: A]): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) + def trySplit(): Spliterator[A] = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToGenericSpliterator[A](undersplit, mapping) + } +} +class IntToDoubleSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Double) extends Spliterator.OfDouble { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.DoubleConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfDouble = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToDoubleSpliterator(undersplit, mapping) + } +} +class IntToLongSpliterator(private val underlying: Spliterator.OfInt, mapping: Int => Long) extends Spliterator.OfLong { + def characteristics = underlying.characteristics + def estimateSize() = underlying.estimateSize() + def tryAdvance(f: java.util.function.LongConsumer): Boolean = underlying.tryAdvance(new java.util.function.IntConsumer{ def accept(a: Int): Unit = { f.accept(mapping(a)) } }) + def trySplit(): Spliterator.OfLong = { + val undersplit = underlying.trySplit() + if (undersplit == null) null + else new IntToLongSpliterator(undersplit, mapping) + } +} + +class SpliteratorStepper[A](sp: Spliterator[A]) extends AnyStepper[A] { + override def trySplit(): AnyStepper[A] = { + val r = sp.trySplit() + if (r == null) null else new SpliteratorStepper(r) + } + + var cache: AnyRef = null + + override def hasStep: Boolean = cache != null || sp.tryAdvance(x => cache = x.asInstanceOf[AnyRef]) + + override def nextStep(): A = if (hasStep) { + val r = cache + cache = null + r.asInstanceOf[A] + } else throw new NoSuchElementException("") + + override def estimateSize: Long = sp.estimateSize() + + override def characteristics: Int = sp.characteristics() +} + +class StepperTest { + def subs[Z, A, CC <: Stepper[A]](zero: Z)(s: Stepper[A])(f: Stepper[A] => Z, op: (Z, Z) => Z): Z = { + val ss = s.substep() + if (ss == null) op(zero, f(s)) + else { + val left = subs(zero)(ss)(f, op) + subs(left)(s)(f, op) + } + } + + val sizes = Vector(0, 1, 2, 4, 15, 17, 2512) + def sources: Vector[(Int, Stepper[Int])] = sizes.flatMap{ i => + Vector( + i -> new IncStepperA(i), + i -> new SpliteratorStepper(new IncSpliterator(i).asInstanceOf[Spliterator[Int]]), + i -> new MappingStepper[Int,Int](new IncStepperA(i), x => x), + i -> new MappingStepper[Long, Int](new SpliteratorStepper(new IntToLongSpliterator(new IncSpliterator(i), _.toLong).asInstanceOf[Spliterator[Long]]), _.toInt), + i -> new MappingStepper[Double, Int](new SpliteratorStepper(new IntToDoubleSpliterator(new IncSpliterator(i), _.toDouble).asInstanceOf[Spliterator[Double]]), _.toInt), + i -> new MappingStepper[String, Int](new SpliteratorStepper(new IntToGenericSpliterator[String](new IncSpliterator(i), _.toString)), _.toInt) + ) + } + + @Test + def stepping(): Unit = { + sources.foreach{ case (i, s) => assert((0 until i).forall{ j => s.hasStep && s.nextStep() == j } && !s.hasStep) } + sources.foreach{ case (i, s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while (x.hasStep) { val y = x.nextStep(); assert(!(set contains y)); set += y } + 0 + }, + _ + _ + ) + assert((0 until i).toSet == set) + } + } + + @Test + def trying(): Unit = { + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + while (s.hasStep) { val y = s.nextStep(); assert(!(set contains y)); set += y } + assert((0 until i).toSet == set) + } + sources.foreach{ case (i,s) => + val set = collection.mutable.BitSet.empty + subs(0)(s)( + { x => + while (x.hasStep) { val y = x.nextStep(); assert(!(set contains y)); set += y } + 0 + }, + _ + _ + ) + assertTrue(s.getClass.getName + s" said [0, $i) was " + set.mkString("{", " ", "}"), (0 until i).toSet == set) + } + } + + @Test + def substepping(): Unit = { + sources.foreach{ case (i,s) => + val ss = s.substep() + assertEquals(ss == null, i < 2) + if (ss != null) { + assertTrue(s.hasStep) + assertTrue(ss.hasStep) + val c1 = s.count() + val c2 = ss.count() + assertEquals(s"$i != $c1 + $c2 from ${s.getClass.getName}", i, c1 + c2) + } + else assertEquals(i, s.count()) + } + } + + @Test + def characteristically(): Unit = { + val expected = Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED + sources.foreach{ case (_,s) => assertEquals(s.characteristics, expected)} + sources.foreach{ case (_,s) => subs(0)(s)(x => { assertEquals(x.characteristics, expected); 0 }, _ + _) } + } + + @Test + def count_only(): Unit = { + sources.foreach{ case (i, s) => assertEquals(i, s.count()) } + sources.foreach{ case (i, s) => assertEquals(i, subs(0)(s)(_.count().toInt, _ + _)) } + } + + @Test + def count_conditionally(): Unit = { + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), s.count(_ % 3 == 0)) } + sources.foreach{ case (i, s) => assertEquals((0 until i).count(_ % 3 == 0), subs(0)(s)(_.count(_ % 3 == 0).toInt, _ + _)) } + } + + @Test + def existence(): Unit = { + sources.foreach{ case (i, s) => assert(i > 0 == s.exists(_ >= 0)) } + sources.foreach{ case (i, s) => assert(i > 16 == s.exists(_ % 17 == 16)) } + sources.foreach{ case (i, s) => assert(i > 0 == subs(false)(s)(_.exists(_ >= 0), _ || _)) } + sources.foreach{ case (i, s) => assert(i > 16 == subs(false)(s)(_.exists(_ % 17 == 16), _ || _)) } + } + + @Test + def finding(): Unit = { + for (k <- 0 until 100) { + (sources zip sources).foreach{ case ((i,s), (j,t)) => + val x = scala.util.Random.nextInt(math.min(i,j)+3) + val a = s.find(_ == x) + val b = subs(None: Option[Int])(t)(_.find(_ == x), _ orElse _) + assertEquals(a, b) + assertEquals(a.isDefined, x < math.min(i,j)) + } + } + } + + @Test + def folding(): Unit = { + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, s.fold("")(_ + _.toString)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).mkString, subs("")(s)(_.fold("")(_ + _.toString), _ + _)) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, s.fold(0.0)(_ + _), 1e-10) } + sources.foreach{ case (i,s) => assertEquals((0 until i).map(_.toDouble).sum, subs(0.0)(s)(_.fold(0.0)(_ + _), _ + _), 1e-10) } + } + + @Test + def foldingUntil(): Unit = { + def expected(i: Int) = (0 until i).scan(0)(_ + _).dropWhile(_ < 6*i).headOption.getOrElse((0 until i).sum) + sources.foreach{ case (i,s) => assertEquals(expected(i), s.foldTo(0)(_ + _)(_ >= 6*i)) } + sources.foreach{ case (_,s) => assertEquals(-1, s.foldTo(-1)(_ * _)(_ => true)) } + sources.foreach{ case (i,s) => + val ss = s.substep() + val x = s.foldTo( if (ss == null) 0 else ss.foldTo(0)(_ + _)(_ >= 6*i) )(_ + _)(_ >= 6*i) + assertEquals(expected(i), x) + } + } + + @Test + def foreaching(): Unit = { + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + s.foreach( clq add _.toString ) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + sources.foreach{ case (i,s) => + val clq = new java.util.concurrent.ConcurrentLinkedQueue[String] + subs(())(s)(_.foreach( clq add _.toString ), (_, _) => ()) + assertEquals((0 until i).map(_.toString).toSet, Iterator.continually(if (!clq.isEmpty) Some(clq.poll) else None).takeWhile(_.isDefined).toSet.flatten) + } + } + + @Test + def reducing(): Unit = { + sources.foreach{ case (i,s) => + if (i==0) assertEquals(s.hasStep, false) + else assertEquals((0 until i).sum, s.reduce(_ + _)) + } + sources.foreach{ case (i,s) => + assertEquals((0 until i).sum, subs(0)(s)(x => if (!x.hasStep) 0 else x.reduce(_ + _), _ + _)) + } + } + + @Test + def iterating(): Unit = { + sources.foreach{ case (i, s) => assert(Iterator.range(0,i) sameElements s.iterator) } + } + + @Test + def spliterating(): Unit = { + sources.foreach{ case (i,s) => + var sum = 0 + s.spliterator.asInstanceOf[Spliterator[Int]].forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sum += i } }) + assertEquals(sum, (0 until i).sum) + } + sources.foreach{ case (i,s) => + val sum = subs(0)(s)(x => { var sm = 0; x.spliterator.asInstanceOf[Spliterator[Int]].forEachRemaining(new java.util.function.Consumer[Int]{ def accept(i: Int): Unit = { sm += i } }); sm }, _ + _) + assertEquals(sum, (0 until i).sum) + } + } +} + diff --git a/src/test/scala-2.13+/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala-2.13+/scala/compat/java8/StreamConvertersTest.scala new file mode 100644 index 0000000..0beb9ae --- /dev/null +++ b/src/test/scala-2.13+/scala/compat/java8/StreamConvertersTest.scala @@ -0,0 +1,303 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8 + +import scala.language.higherKinds + +import org.junit.Test +import org.junit.Assert._ + +import java.util.stream._ +import StreamConverters._ + +class StreamConvertersTest { + + def assertEq[A](a1: A, a2: A, s: String): Unit = { assertEquals(s, a1, a2) } // Weird order normally! + def assertEq[A](a1: A, a2: A): Unit = { assertEq(a1, a2, "not equal") } + def assert(b: Boolean): Unit = { assertTrue(b) } + def assert(b: Boolean, s: String): Unit = { assertTrue(s, b) } + + def arrayO(n: Int) = (1 to n).map(_.toString).toArray + def arrayD(n: Int) = (1 to n).map(_.toDouble).toArray + def arrayI(n: Int) = (1 to n).toArray + def arrayL(n: Int) = (1 to n).map(_.toLong).toArray + + def newStream(n: Int) = java.util.Arrays.stream(arrayO(n)) + def newDoubleStream(n: Int) = java.util.Arrays.stream(arrayD(n)) + def newIntStream(n: Int) = java.util.Arrays.stream(arrayI(n)) + def newLongStream(n: Int) = java.util.Arrays.stream(arrayL(n)) + + val ns = Vector(0, 1, 2, 12, 15, 16, 17, 31, 32, 33, 151, 1298, 7159) + + @Test + def streamAccumulate(): Unit = { + for (n <- ns) { + val vecO = arrayO(n).toVector + val accO = newStream(n).parallel.accumulate + assertEq(vecO, newStream(n).accumulate.to(Vector), s"stream $n to vector") + assertEq(vecO, accO.to(Vector), s"stream $n to vector in parallel") + assertEq(vecO, accO.toArray.toVector, s"stream $n to vector via array in parallel") + assertEq(vecO, accO.iterator.toVector, s"stream $n to vector via iterator in parallel") + assertEq(vecO, accO.toList.toVector, s"stream $n to vector via list in parallel") + assert((0 until accO.size.toInt).forall(i => vecO(i) == accO(i)), s"stream $n indexed via accumulator") + assert(accO.isInstanceOf[scala.compat.java8.collectionImpl.Accumulator[_]], s"stream $n to generic accumulator") + + for (boxless <- Seq(false, true)) { + val sbox = (if (boxless) "" else "(boxed)") + val vecD = arrayD(n).toVector + val accD = + if (boxless) newDoubleStream(n).parallel.accumulate + else newDoubleStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecD, newDoubleStream(n).accumulate.to(Vector), s"double stream $n to vector $sbox") + assertEq(vecD, accD.to(Vector), s"double stream $n to vector in parallel $sbox") + assertEq(vecD, accD.toArray.toVector, s"double stream $n to vector via array in parallel $sbox") + assertEq(vecD, accD.iterator.toVector, s"double stream $n to vector via iterator in parallel $sbox") + assertEq(vecD, accD.toList.toVector, s"double stream $n to vector via list in parallel $sbox") + assert((0 until accD.size.toInt).forall(i => vecD(i) == accD(i)), s"double stream $n indexed via accumulator $sbox") + assert(accD.isInstanceOf[scala.compat.java8.collectionImpl.DoubleAccumulator], s"double stream $n to generic accumulator $sbox") + + val vecI = arrayI(n).toVector + val accI = + if (boxless) newIntStream(n).parallel.accumulate + else newIntStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecI, newIntStream(n).accumulate.to(Vector), s"int stream $n to vector $sbox") + assertEq(vecI, accI.to(Vector), s"int stream $n to vector in parallel $sbox") + assertEq(vecI, accI.toArray.toVector, s"int stream $n to vector via array in parallel $sbox") + assertEq(vecI, accI.iterator.toVector, s"int stream $n to vector via iterator in parallel $sbox") + assertEq(vecI, accI.toList.toVector, s"int stream $n to vector via list in parallel $sbox") + assert((0 until accI.size.toInt).forall(i => vecI(i) == accI(i)), s"int stream $n indexed via accumulator $sbox") + assert(accI.isInstanceOf[scala.compat.java8.collectionImpl.IntAccumulator], s"int stream $n to generic accumulator $sbox") + + val vecL = arrayL(n).toVector + val accL = + if (boxless) newLongStream(n).parallel.accumulate + else newLongStream(n).boxed.parallel.accumulatePrimitive + assertEq(vecL, newLongStream(n).accumulate.to(Vector), s"long stream $n to vector $sbox") + assertEq(vecL, accL.to(Vector), s"long stream $n to vector in parallel $sbox") + assertEq(vecL, accL.toArray.toVector, s"long stream $n to vector via array in parallel $sbox") + assertEq(vecL, accL.iterator.toVector, s"long stream $n to vector via iterator in parallel $sbox") + assertEq(vecL, accL.toList.toVector, s"long stream $n to vector via list in parallel $sbox") + assert((0 until accL.size.toInt).forall(i => vecL(i) == accL(i)), s"long stream $n indexed via accumulator $sbox") + assert(accL.isInstanceOf[scala.compat.java8.collectionImpl.LongAccumulator], s"long stream $n to generic accumulator $sbox") + } + } + } + + @Test + def streamToScala(): Unit = { + for (n <- ns) { + val vecO = arrayO(n).toVector + assertEq(vecO, newStream(n).toScala(Vector)) + assertEq(vecO, newStream(n).parallel.toScala(Vector)) + assertEq(vecO, newStream(n).toScala[Vector]) + assertEq(vecO, newStream(n).parallel.toScala[Vector]) + + val vecD = arrayD(n).toVector + assertEq(vecD, newDoubleStream(n).toScala(Vector)) + assertEq(vecD, newDoubleStream(n).parallel.toScala(Vector)) + assertEq(vecD, newDoubleStream(n).toScala[Vector]) + assertEq(vecD, newDoubleStream(n).parallel.toScala[Vector]) + + val vecI = arrayI(n).toVector + assertEq(vecI, newIntStream(n).toScala(Vector)) + assertEq(vecI, newIntStream(n).parallel.toScala(Vector)) + assertEq(vecI, newIntStream(n).toScala[Vector]) + assertEq(vecI, newIntStream(n).parallel.toScala[Vector]) + + val vecL = arrayL(n).toVector + assertEq(vecL, newLongStream(n).toScala(Vector)) + assertEq(vecL, newLongStream(n).parallel.toScala(Vector)) + assertEq(vecL, newLongStream(n).toScala[Vector]) + assertEq(vecL, newLongStream(n).parallel.toScala[Vector]) + } + } + + @Test + def streamUnbox(): Unit = { + assert(newDoubleStream(1).boxed.unboxed.isInstanceOf[DoubleStream]) + assert(newIntStream(1).boxed.unboxed.isInstanceOf[IntStream]) + assert(newLongStream(1).boxed.unboxed.isInstanceOf[LongStream]) + } + + import collection.mutable.{ ArrayBuffer, ArraySeq } + def abufO(n: Int) = { val ab = new ArrayBuffer[String]; arrayO(n).foreach(ab += _); ab } + def abufD(n: Int) = { val ab = new ArrayBuffer[Double]; arrayD(n).foreach(ab += _); ab } + def abufI(n: Int) = { val ab = new ArrayBuffer[Int]; arrayI(n).foreach(ab += _); ab } + def abufL(n: Int) = { val ab = new ArrayBuffer[Long]; arrayL(n).foreach(ab += _); ab } + def wrapO(n: Int): ArraySeq[String] = arrayO(n) + def wrapD(n: Int): ArraySeq[Double] = arrayD(n) + def wrapI(n: Int): ArraySeq[Int] = arrayI(n) + def wrapL(n: Int): ArraySeq[Long] = arrayL(n) + def vectO(n: Int) = arrayO(n).toVector + def vectD(n: Int) = arrayD(n).toVector + def vectI(n: Int) = arrayI(n).toVector + def vectL(n: Int) = arrayL(n).toVector + def genhset[A](aa: Array[A]) = { val hs = new collection.mutable.HashSet[A]; aa.foreach(hs += _); hs } + def hsetO(n: Int) = genhset(arrayO(n)) + def hsetD(n: Int) = genhset(arrayD(n)) + def hsetI(n: Int) = genhset(arrayI(n)) + def hsetL(n: Int) = genhset(arrayL(n)) + + @Test + def scalaToStream(): Unit = { + for (n <- ns) { + val arrO = arrayO(n) + val seqO = arrO.toSeq + val abO = abufO(n) + val wrO = wrapO(n) + val vecO = vectO(n) + val hsO = hsetO(n) + // Seems like a lot of boilerplate, but we need it to test implicit resolution + assertEq(seqO, seqO.seqStream.toScala[Seq]) +// assertEq(seqO, seqO.stepper.parStream.toScala[Seq]) // Must go through stepper if we're unsure whether we can parallelize well + assertEq(seqO, arrO.seqStream.toScala[Seq]) + assertEq(seqO, arrO.parStream.toScala[Seq]) + assertEq(seqO, abO.seqStream.toScala[Seq]) + assertEq(seqO, abO.parStream.toScala[Seq]) + assertEq(seqO, wrO.seqStream.toScala[Seq]) + assertEq(seqO, wrO.parStream.toScala[Seq]) + assertEq(seqO, vecO.seqStream.toScala[Seq]) + assertEq(seqO, vecO.parStream.toScala[Seq]) +// assertEq(seqO, hsO.seqStream.toScala[Seq].sortBy(_.toInt)) +// assertEq(seqO, hsO.parStream.toScala[Seq].sortBy(_.toInt)) + + val arrD = arrayD(n) + val seqD = arrD.toSeq + val abD = abufD(n) + val wrD = wrapD(n) + val vecD = vectD(n) + val hsD = hsetD(n) + assertEq(seqD, seqD.seqStream.toScala[Seq]) +// assertEq(seqD, seqD.stepper.parStream.toScala[Seq]) + assertEq(seqD, arrD.seqStream.toScala[Seq]) + assertEq(seqD, arrD.parStream.toScala[Seq]) + assert(arrD.seqStream.isInstanceOf[DoubleStream]) + assert(arrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, abD.seqStream.toScala[Seq]) + assertEq(seqD, abD.parStream.toScala[Seq]) + assert(abD.seqStream.isInstanceOf[DoubleStream]) + assert(abD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrD.seqStream.isInstanceOf[DoubleStream]) + assert(wrD.parStream.isInstanceOf[DoubleStream]) + assertEq(seqD, vecD.seqStream.toScala[Seq]) + assertEq(seqD, vecD.parStream.toScala[Seq]) + assert(vecD.seqStream.isInstanceOf[DoubleStream]) + assert(vecD.parStream.isInstanceOf[DoubleStream]) +// assertEq(seqD, hsD.seqStream.toScala[Seq].sorted) +// assertEq(seqD, hsD.parStream.toScala[Seq].sorted) +// assert(hsD.seqStream.isInstanceOf[DoubleStream]) +// assert(hsD.parStream.isInstanceOf[DoubleStream]) + + val arrI = arrayI(n) + val seqI = arrI.toSeq + val abI = abufI(n) + val wrI = wrapI(n) + val vecI = vectI(n) + val hsI = hsetI(n) + assertEq(seqI, seqI.seqStream.toScala[Seq]) +// assertEq(seqI, seqI.stepper.parStream.toScala[Seq]) + assertEq(seqI, arrI.seqStream.toScala[Seq]) + assertEq(seqI, arrI.parStream.toScala[Seq]) + assert(arrI.seqStream.isInstanceOf[IntStream]) + assert(arrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, abI.seqStream.toScala[Seq]) + assertEq(seqI, abI.parStream.toScala[Seq]) + assert(abI.seqStream.isInstanceOf[IntStream]) + assert(abI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, wrI.seqStream.toScala[Seq]) + assertEq(seqI, wrI.parStream.toScala[Seq]) + assert(wrI.seqStream.isInstanceOf[IntStream]) + assert(wrI.parStream.isInstanceOf[IntStream]) + assertEq(seqI, vecI.seqStream.toScala[Seq]) + assertEq(seqI, vecI.parStream.toScala[Seq]) + assert(vecI.seqStream.isInstanceOf[IntStream]) + assert(vecI.parStream.isInstanceOf[IntStream]) +// assertEq(seqI, hsI.seqStream.toScala[Seq].sorted) +// assertEq(seqI, hsI.parStream.toScala[Seq].sorted) +// assert(hsI.seqStream.isInstanceOf[IntStream]) +// assert(hsI.parStream.isInstanceOf[IntStream]) + + val arrL = arrayL(n) + val seqL = arrL.toSeq + val abL = abufL(n) + val wrL = wrapL(n) + val vecL = vectL(n) + val hsL = hsetL(n) + assertEq(seqL, seqL.seqStream.toScala[Seq]) +// assertEq(seqL, seqL.stepper.parStream.toScala[Seq]) + assertEq(seqL, arrL.seqStream.toScala[Seq]) + assertEq(seqL, arrL.parStream.toScala[Seq]) + assert(arrL.seqStream.isInstanceOf[LongStream]) + assert(arrL.parStream.isInstanceOf[LongStream]) + assertEq(seqL, abL.seqStream.toScala[Seq]) + assertEq(seqL, abL.parStream.toScala[Seq]) + assert(abL.seqStream.isInstanceOf[LongStream]) + assert(abL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(wrL.seqStream.isInstanceOf[LongStream]) + assert(wrL.parStream.isInstanceOf[LongStream]) + assertEq(seqD, wrD.seqStream.toScala[Seq]) + assertEq(seqD, wrD.parStream.toScala[Seq]) + assert(vecL.seqStream.isInstanceOf[LongStream]) + assert(vecL.parStream.isInstanceOf[LongStream]) +// assertEq(seqL, hsL.seqStream.toScala[Seq].sorted) +// assertEq(seqL, hsL.parStream.toScala[Seq].sorted) +// assert(hsL.seqStream.isInstanceOf[LongStream]) +// assert(hsL.parStream.isInstanceOf[LongStream]) + } + } + + @Test + def primitiveStreamTypes(): Unit = { + // Unboxed native + widening Steppers available: + assertEquals(Vector[Int](1, 2, 3), (Array[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Array[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[String]("a", "b"), (Array[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) + + // Boxed collections, widening via boxed AnySteppers: + assertEquals(Vector[Int](1, 2, 3), (Vector[Int](1, 2, 3).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[Short](1.toShort, 2.toShort, 3.toShort), (Vector[Short](1.toShort, 2.toShort, 3.toShort).seqStream: IntStream).toScala[Vector]) + assertEquals(Vector[String]("a", "b"), (Vector[String]("a", "b").seqStream: Stream[String]).toScala[Vector]) + } + + @Test + def issue_87(): Unit = { + // Vectors that are generated from other vectors tend _not_ to + // have all their display vectors consistent; the cached vectors + // are correct, but the higher-level vector does _not_ contain + // the cached vector in the correct place (for efficiency)! This + // is called being "dirty", and needs to be handled specially. + val dirtyDisplayVector = Vector.fill(120)("a").slice(0, 40) + val shouldNotNPE = + dirtyDisplayVector.seqStream.collect(Collectors.toList()) + assertEq(shouldNotNPE.toArray(new Array[String](0)).toVector, dirtyDisplayVector, "Vector[Any].seqStream (with dirty display)") + + val dirtyDisplayVectorInt = Vector.fill(120)(999).slice(0, 40) + val shouldNotNPEInt = + dirtyDisplayVectorInt.seqStream.sum() + assertEq(shouldNotNPEInt, dirtyDisplayVectorInt.sum, "Vector[Int].seqStream (with dirty display)") + + val dirtyDisplayVectorLong = Vector.fill(120)(99999999999L).slice(0, 40) + val shouldNotNPELong = + dirtyDisplayVectorLong.seqStream.sum() + assertEq(shouldNotNPELong, dirtyDisplayVectorLong.sum, "Vector[Long].seqStream (with dirty display)") + + val dirtyDisplayVectorDouble = Vector.fill(120)(0.1).slice(0, 40) + val shouldNotNPEDouble = + math.rint(dirtyDisplayVectorDouble.seqStream.sum() * 10) + assertEq(shouldNotNPEDouble, math.rint(dirtyDisplayVectorDouble.sum * 10), "Vector[Double].seqStream (with dirty display)") + } +} diff --git a/src/test/scala/scala/compat/java8/StepConvertersTest.scala b/src/test/scala-2.13-/scala/compat/java8/StepConvertersTest.scala similarity index 100% rename from src/test/scala/scala/compat/java8/StepConvertersTest.scala rename to src/test/scala-2.13-/scala/compat/java8/StepConvertersTest.scala diff --git a/src/test/scala/scala/compat/java8/StepperTest.scala b/src/test/scala-2.13-/scala/compat/java8/StepperTest.scala similarity index 100% rename from src/test/scala/scala/compat/java8/StepperTest.scala rename to src/test/scala-2.13-/scala/compat/java8/StepperTest.scala diff --git a/src/test/scala/scala/compat/java8/StreamConvertersTest.scala b/src/test/scala-2.13-/scala/compat/java8/StreamConvertersTest.scala similarity index 100% rename from src/test/scala/scala/compat/java8/StreamConvertersTest.scala rename to src/test/scala-2.13-/scala/compat/java8/StreamConvertersTest.scala From 6593f181adcb933adc955fb82829e6fef520a491 Mon Sep 17 00:00:00 2001 From: Ikhun Um Date: Sat, 20 Jul 2019 18:21:22 +0900 Subject: [PATCH 168/340] Add maven release badge for 2.13 in README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5bb5b5..6ca6acc 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# scala-java8-compat [![Build Status](https://travis-ci.org/scala/scala-java8-compat.svg?branch=master)](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) +# scala-java8-compat [![Build Status](https://travis-ci.org/scala/scala-java8-compat.svg?branch=master)](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.13) + A Java 8 compatibility kit for Scala. From f8129056edaa795f9ca7a2e7cc75c8569cb1fa8f Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 7 Sep 2019 09:39:37 +0200 Subject: [PATCH 169/340] Update sbt to 1.3.0 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index c0bab04..080a737 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.8 +sbt.version=1.3.0 From a21156fc1cf0086b21983ac39a617e8590adc2d5 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 17 Sep 2019 21:22:27 +0200 Subject: [PATCH 170/340] New scala-module-plugin with sbt-ci-release / travisci / dynver / header --- .travis.yml | 29 ++++++---------- admin/README.md | 69 ------------------------------------- admin/build.sh | 44 ----------------------- admin/encryptEnvVars.sh | 11 ------ admin/genKeyPair.sh | 40 --------------------- admin/gpg.sbt | 1 - admin/publish-settings.sbt | 8 ----- admin/pubring.asc | 18 ---------- admin/secring.asc.enc | Bin 1872 -> 0 bytes build.sbt | 67 +++++++++++++++++------------------ build.sh | 67 +++++++++++++++++++++++++++++++++++ project/plugins.sbt | 9 +---- 12 files changed, 111 insertions(+), 252 deletions(-) delete mode 100644 admin/README.md delete mode 100755 admin/build.sh delete mode 100755 admin/encryptEnvVars.sh delete mode 100755 admin/genKeyPair.sh delete mode 100644 admin/gpg.sbt delete mode 100644 admin/publish-settings.sbt delete mode 100644 admin/pubring.asc delete mode 100644 admin/secring.asc.enc create mode 100755 build.sh diff --git a/.travis.yml b/.travis.yml index a0e622d..c8b0fa9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,17 @@ language: scala scala: - - 2.13.0 - - 2.12.8 - 2.11.12 + - 2.12.8 + - 2.13.0 env: - global: - # PGP_PASSPHRASE - - secure: "BzgzRZLYa52rS/hBfzf43b++CfDhdcd3Mmu8tsyBHgThSQOd2YBLbV5kWD8aYVFKVHfW7XX0PTe3F+rR/fFZqGItE6o8Px0Y7Vzb5pqjlaQdxFEJ+WrsnshS0xuAKZ7OwVHRp+d+jznaCwRxEo2vpW3ko1OPAJ8cxfhVL/4C1I0=" - # SONA_USER - - secure: "lx2qFeFxh9AFmyHR7hH4Qf9flIEx8VgYj6ebzuxp1cc1ZZiXHC1256x0bHFDUH9bhJACOazOrco/+v6MBAriBkWxLBc98FrC6OkVeQMFW2ffWSBuHRclilKsQA/Lsgc81Wg+WV105hOqUNAkTXgroblInNt+KS+DhC/8FVoh9ZY=" - # SONA_PASS - - secure: "FZC+FZnBNeklA150vW5QDZJ5J7t+DExJrgyXWM46Wh0MobjH8cvydgC3qatItb0rDBV8l7zO1LDwl2KEi92aefw2a8E49z6qVOHgUXiI3SAx7M0UO0FFeKPmTXCLcBlbnGLcUqNjIZfuIEufQvPblKTl8qN4eMmcMn9jsNzJr28=" - matrix: - - ADOPTOPENJDK=8 - - ADOPTOPENJDK=11 + - ADOPTOPENJDK=8 + - ADOPTOPENJDK=11 before_install: # adding $HOME/.sdkman to cache would create an empty directory, which interferes with the initial installation - - "[[ -d $HOME/.sdkman/bin/ ]] || rm -rf $HOME/.sdkman/" + - "[[ -d $HOME/.sdkman/bin ]] || rm -rf $HOME/.sdkman/" - curl -sL https://get.sdkman.io | bash - echo sdkman_auto_answer=true > $HOME/.sdkman/etc/config - source "$HOME/.sdkman/bin/sdkman-init.sh" @@ -28,10 +20,9 @@ install: - sdk install java $(sdk list java | grep -o "$ADOPTOPENJDK\.[0-9\.]*hs-adpt" | head -1) - unset JAVA_HOME - java -Xmx32m -version - - javac -J-Xmx32m -version + - git fetch --tags # get all tags for sbt-dynver -script: - - admin/build.sh +script: ./build.sh notifications: email: @@ -39,10 +30,12 @@ notifications: - seth.tisue@lightbend.com before_cache: - - find $HOME/.sbt -name "*.lock" | xargs rm - - find $HOME/.ivy2/cache -name "ivydata-*.properties" | xargs rm + - rm -f $HOME/.ivy2/.sbt.ivy.lock + - find $HOME/.ivy2/cache -name "ivydata-*.properties" | xargs rm + - find $HOME/.sbt -name "*.lock" | xargs rm cache: directories: - $HOME/.ivy2/cache - $HOME/.sbt + - $HOME/.cache/coursier - $HOME/.sdkman diff --git a/admin/README.md b/admin/README.md deleted file mode 100644 index 3e9d1bf..0000000 --- a/admin/README.md +++ /dev/null @@ -1,69 +0,0 @@ -## Tag Driven Releasing - -### Initial setup for the repository - -To configure tag driven releases from Travis CI. - - 1. Generate a key pair for this repository with `./admin/genKeyPair.sh`. - Edit `.travis.yml` and `admin/build.sh` as prompted. - 1. Publish the public key to https://pgp.mit.edu - 1. Store other secrets as encrypted environment variables with `./admin/encryptEnvVars.sh`. - Edit `.travis.yml` as prompted. - 1. Edit `.travis.yml` to use `./admin/build.sh` as the build script, - and edit that script to use the tasks required for this project. - Ensure that `RELEASE_COMBO` is `true` for build matrix combinations - that should be released to sonatype (when building a tag). - -It is important to add comments in `.travis.yml` to identify the name -of each environment variable encoded in a `secure` section. - -After these steps, your `.travis.yml` should contain config of the form: - -``` -language: scala - -jdk: - - openjdk6 - - oraclejdk8 - -scala: - - 2.11.12 - - 2.12.6 - -env: - global: - # PGP_PASSPHRASE - - secure: "XXXXXX" - # SONA_USER - - secure: "XXXXXX" - # SONA_PASS - - secure: "XXXXXX" - -script: admin/build.sh - -notifications: - email: - - a@b.com -``` - -If Sonatype credentials change in the future, step 3 can be repeated -without generating a new key. - -### Testing - - 1. Follow the release process below to create a dummy release (e.g., `v0.1.0-TEST1`). - Confirm that the release was staged to Sonatype but do not release it to Maven - central. Instead, drop the staging repository. - -### Performing a release - - 1. Create a GitHub "Release" with a corresponding tag (e.g., `v0.1.1`) via the GitHub - web interface. - 1. The release will be published using the Scala and JVM version combinations specified - in the travis build matrix where `[ "$RELEASE_COMBO" = "true" ]`. - - If you need to release against a different Scala version, create a new commit that modifies - `.travis.yml` and push a new tag, e.g., `v1.2.3#2.13.0-M5`. The suffix after `#` is ignored. - 1. Travis CI will schedule a build for this release. Review the build logs. - 1. Log into https://oss.sonatype.org/ and identify the staging repository. - 1. Sanity check its contents. - 1. Release staging repository to Maven and send out release announcement. diff --git a/admin/build.sh b/admin/build.sh deleted file mode 100755 index 929aa55..0000000 --- a/admin/build.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -e - -# Builds of tagged revisions are published to sonatype staging. - -# Travis runs a build on new revisions and on new tags, so a tagged revision is built twice. -# Builds for a tag have TRAVIS_TAG defined, which we use for identifying tagged builds. -# Checking the local git clone would not work because git on travis does not fetch tags. - -# The version number to be published is extracted from the tag, e.g., v1.2.3 publishes -# version 1.2.3 on all combinations of the travis matrix where `[ "$RELEASE_COMBO" = "true" ]`. - -# In order to build a previously released version against a new (binary incompatible) Scala release, -# a new commit that modifies (and prunes) the Scala versions in .travis.yml needs to be added on top -# of the existing tag. Then a new tag can be created for that commit, e.g., `v1.2.3#2.13.0-M5`. -# Everything after the `#` in the tag name is ignored. - -RELEASE_COMBO=true - -verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" -tagPat="^v$verPat(#.*)?$" - -if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then - tagVer=$(echo $TRAVIS_TAG | sed s/#.*// | sed s/^v//) - publishVersion='set every version := "'$tagVer'"' - - if [ "$RELEASE_COMBO" = "true" ]; then - currentJvmVer=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}' | sed 's/^1\.//' | sed 's/[^0-9].*//') - echo "Releasing $tagVer with Scala $TRAVIS_SCALA_VERSION on Java version $currentJvmVer." - - publishTask="publishSigned" - - cat admin/gpg.sbt >> project/plugins.sbt - cp admin/publish-settings.sbt . - - # Copied from the output of genKeyPair.sh - K=$encrypted_1ce132863fa7_key - IV=$encrypted_1ce132863fa7_iv - openssl aes-256-cbc -K $K -iv $IV -in admin/secring.asc.enc -out admin/secring.asc -d - fi -fi - -sbt "++$TRAVIS_SCALA_VERSION" "$publishVersion" clean test publishLocal "$publishTask" diff --git a/admin/encryptEnvVars.sh b/admin/encryptEnvVars.sh deleted file mode 100755 index b625667..0000000 --- a/admin/encryptEnvVars.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# -# Encrypt sonatype credentials so that they can be -# decrypted in trusted builds on Travis CI. -# -set -e - -read -s -p 'SONA_USER: ' SONA_USER -travis encrypt SONA_USER="$SONA_USER" -read -s -p 'SONA_PASS: ' SONA_PASS -travis encrypt SONA_PASS="$SONA_PASS" diff --git a/admin/genKeyPair.sh b/admin/genKeyPair.sh deleted file mode 100755 index 11f7a1e..0000000 --- a/admin/genKeyPair.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# -# Generates a key pair for this repository to sign artifacts. -# Encrypt the private key and its passphrase in trusted builds -# on Travis CI. -# -set -e - -# Based on https://gist.github.com/kzap/5819745: -function promptDelete() { - if [[ -f "$1" ]]; then - echo About to delete $1, Enter for okay / CTRL-C to cancel - read - rm "$1" - fi -} -for f in admin/secring.asc.enc admin/secring.asc admin/pubring.asc; do promptDelete "$f"; done - -echo Generating key pair. Please enter 1. repo name 2. scala-internals@googlegroups.com, 3. a new passphrase -cp admin/gpg.sbt project -sbt 'set pgpReadOnly := false' \ - 'set pgpPublicRing := file("admin/pubring.asc")' \ - 'set pgpSecretRing := file("admin/secring.asc")' \ - 'pgp-cmd gen-key' -rm project/gpg.sbt - -echo ============================================================================================ -echo Encrypting admin/secring.asc. Update K and IV variables in admin/build.sh accordingly. -echo ============================================================================================ -travis encrypt-file admin/secring.asc -rm admin/secring.asc -mv secring.asc.enc admin - -echo ============================================================================================ -echo Encrypting environment variables. Add each to a line in .travis.yml. Include a comment -echo with the name of the corresponding variable -echo ============================================================================================ -read -s -p 'PGP_PASSPHRASE: ' PGP_PASSPHRASE -travis encrypt PGP_PASSPHRASE="$PGP_PASSPHRASE" - diff --git a/admin/gpg.sbt b/admin/gpg.sbt deleted file mode 100644 index e6f00f4..0000000 --- a/admin/gpg.sbt +++ /dev/null @@ -1 +0,0 @@ -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2-1") // only added when publishing diff --git a/admin/publish-settings.sbt b/admin/publish-settings.sbt deleted file mode 100644 index 026c6ee..0000000 --- a/admin/publish-settings.sbt +++ /dev/null @@ -1,8 +0,0 @@ -def env(key: String) = Option(System.getenv(key)).getOrElse("") - -inThisBuild(Seq( - pgpPassphrase := Some(env("PGP_PASSPHRASE").toArray), - pgpPublicRing := file("admin/pubring.asc"), - pgpSecretRing := file("admin/secring.asc"), - credentials += Credentials("Sonatype Nexus Repository Manager", "oss.sonatype.org", env("SONA_USER"), env("SONA_PASS")) -)) diff --git a/admin/pubring.asc b/admin/pubring.asc deleted file mode 100644 index 5d5dd87..0000000 --- a/admin/pubring.asc +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: BCPG v1.49 - -mQENBFS1xA0BCAC0t2c5MhkWyUbkWsZM4DmIN+/pDjNCr2DNmbIG3gB8i4MI71q/ -fj+Ob0lemjJNnNc4ii6+s9RrOcwR1EU4IA8mO79NN+i2yVUhe0LmOWgyfXvG8Qpg -hLmdMrkgOHK0hpWbXJ0i2NGPch4gI6YRJF95yLojz2KENmiYGmSD8p1It06O2824 -Xhqc5Cm72/qXvonHP1+MugjiPxmyZN3ajSol0P7tZlgB7ikqpyL3kZXkc162bJ+H -U6y6qUCcQqS5VQ7Fv9bIbTNOjN4ELLJn2ffLVe3ujRG6seioL0MfuQ/gV9IpGcGO -Dew8Xu79QdDyVHQKgDy9N/J276JZ4j9nYCCxABEBAAG0NXNjYWxhLWphdmE4LWNv -bXBhdCA8c2NhbGEtaW50ZXJuYWxzQGdvb2dsZWdyb3Vwcy5jb20+iQEcBBMBAgAG -BQJUtcQNAAoJEGQWNEmlKase8pAH/Rb45Px88u7DDT53DU68zh84oDZLv9i46g7g -16KI97nz17F9OEHdkzNEUA3EgCD1d2k+c/GIdQKg3avVdpNM7krK5SSNgHKcwe/F -0YGMxvh+LgeK1JDuXFbwLJKR+7VIGVKkjw+Z2TC8hZfnD6Qy6c4xkukoBs6yfWQO -tf8gSH6oQox4UIOB/+ADyypl9mnRxgdi1uPvd6UJnL/n9UDE8v1k+8WzO34nTVZr -xWN28pAun5VpLuEq4GAr2JRfRiF+N0hGuS+htiU6hnO81BBK+NusWxI9Aitu8Zyh -eulWpROXvUOw1eJequutgyGwEEQkRi+Yu+2eSM2/EPCWiLXkODk= -=Qro7 ------END PGP PUBLIC KEY BLOCK----- diff --git a/admin/secring.asc.enc b/admin/secring.asc.enc deleted file mode 100644 index bc600f9c5570b1643d7bb99b76e206b99c77901e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1872 zcmV-W2e0_dw!pO7Xu$O+KRZibW}N;fRS+~U^U<)JYdp|s za#k#}E78?%vHvQ`o;LTKuznmHgPJY;Tfr^Kqo5Q1^J=>NpI9Q!Zr`|`Ey@rPcR(`X znG88HFK_+VfGwV!Nz(qw!OM}4SL!%So4}q}u@P=-DpkJj(`Uu!;!#+rc+=$HCo)&6 zdzuxtfwjkcN#%ee?xndT#^d5Fkdop_!UU;oJOY3^>phbtr}kUn zfstYauNuVRT)IPHHr~I0JHkwcc*_nu{5#tcWk^DB71hwt9H}s$2=34RvU1bJyzhRJ zkfES!dUVVdd;q65iXw~Yj;>DvA_|Vly$_r;IUjkpST>mrWK1BwqqwC3F^dhOGCeXK z**1LpiuPqaR4%O4a=uaQ{XwsGlE{^Z0vQyFQ7qLDAGK%wZi(m_;rb{JJbF=j@11-0 zQ;z;DS)2n z86r=doGOQ&Bk;}g0B_DW*XY|5-QAck!wnFvKDN*lzZHzB<~th<-mbH-C}d3PD=d)k zUtVw0p_v}Dq7x%;0B_T>oFQw_Us1>;xNB$sl}bk zU9HN7Qy3R;RuJp-e* zxk5jrCZ9Z<*i%oGEUZ;v(6+N-xK&_^Twc|HWLG{&e-d|Haa8?`wnvi06;@^dPu0Q3 z%N1@)T8P?2xPDnD_Kn*EJkhv^Hs_K_``v_cGMJ`yl zFN%jxS>Y7|lD!7%kO!bagC3q=i6r-I+O`p@zjE=#h!^BAII7C0H5ai5&>7N}^fAsc zvEtLvWfTh|rI&0!#MyCKK7R652P<$MXZ7s7!!r2lL8+Ap{Vnz(d67vG^xk%rZCa;P z0U`HmdO@JJpCni9xawICL0M>L8=A1g+D9VWmA z6Hv=#C*I22-7@Dl-VbLfC561mJkTyA&F+7fAGfZA8SKD3%W9jFZcD&Z;SQG6iC#of z)Cd^Cj-dPJ#ITfeS2_cu6q%h~`#(was8{{BW+~dROWo=e#?a^JJo}b(mtj(kR?tPh zq%k+3v7C-I-F|l-_(grXH);$6D`<-4%R?>4kuOG_Zm_xvFp1SHuyzv< z&T?CK!Bqjn8o&lojTOSw@OmkD-@w6#2(<#+Uknv0R|Qwx(4C7W}#b6PpjE??3?WC`l9*=v>)+|U%3lMdmab4L<$ zm>uQ!#9_`BN8cOSkazpu1tcj*0?e-?T+jNZTm0Thk&q#QRzj0~t zjy|%ugVvp-aXzx{A=2(H2-q>RU-MRbIn`a~|1eU1;6O-F7*9Q4Z4Z)f>IH3sjVi=f za$*9ceuqA;mlO>7OX7QQc1#dzn5&r8OKQhFIv0X-rkg-~Xsab^D`^>q+1kn1;1;#H zvYI?WYYBLq+Y)v8&w3VffLq;pzjsNExCPTboSDd5RSUzodD@78=qfiWbA+*?Y`osq z>?G@k$T-^Gpezcd)v6)ZgVd44Gu(YAIOrrNb*n{&Kr#>8Zc3FZbi-2{S!KF4>3P-U-7WozKa_PTwRkpOhW3{9N&0~nYo|;<_upYs;aGqMBSW$+bzBTgpVupj=9r++saNW2`m;8L6ThI5{{aYtWi_>1tnmwE2y KmJ}*KnDT;JlCO3E diff --git a/build.sbt b/build.sbt index 3a2b463..5945b4e 100644 --- a/build.sbt +++ b/build.sbt @@ -1,10 +1,6 @@ -import ScalaModulePlugin._ - -crossScalaVersions in ThisBuild := List("2.13.0", "2.12.8", "2.11.12") - val disableDocs = sys.props("nodocs") == "true" || - // can't build doc on JDK 11 until sbt/sbt#4350 is fixed + // on jdk 11 https://github.com/scala/scala-java8-compat/issues/160, seems to fail the build (not on 8) !sys.props("java.version").startsWith("1.") lazy val JavaDoc = config("genjavadoc") extend Compile @@ -23,9 +19,6 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - organization := "org.scala-lang.modules", - version := "0.9.1-SNAPSHOT", - scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked"), unmanagedSourceDirectories in Compile ++= { @@ -49,21 +42,22 @@ lazy val commonSettings = Seq( }, ) -lazy val fnGen = (project in file("fnGen")). - settings(commonSettings: _*). - settings( +lazy val fnGen = (project in file("fnGen")) + .settings(commonSettings) + .settings( fork in run := true, // Needed if you run this project directly libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value ) -lazy val root = (project in file(".")). - settings(scalaModuleSettings: _*). - settings(commonSettings: _*). - settings( +lazy val scalaJava8Compat = (project in file(".")) + .settings(ScalaModulePlugin.scalaModuleSettings) + .settings(ScalaModulePlugin.scalaModuleSettingsJVM) + .settings(commonSettings) + .settings( name := "scala-java8-compat" - ). - settings( + ) + .settings( fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath OsgiKeys.exportPackage := osgiExport(scalaVersion.value, version.value), @@ -76,7 +70,7 @@ lazy val root = (project in file(".")). libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - mimaPreviousVersion := None, + scalaModuleMimaPreviousVersion := None, testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), @@ -119,23 +113,26 @@ lazy val root = (project in file(".")). }, publishArtifact in packageDoc := !disableDocs - ). - settings( - (inConfig(JavaDoc)(Defaults.configSettings) ++ (if (disableDocs) Nil else Seq( - packageDoc in Compile := (packageDoc in JavaDoc).value, - sources in JavaDoc := { - val allJavaSources = - (target.value / "java" ** "*.java").get ++ - (sources in Compile).value.filter(_.getName.endsWith(".java")) - allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc - }, - javacOptions in JavaDoc := Seq(), - artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.13" cross CrossVersion.full), - scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") - ))): _* - ). - settings( + ) + .settings( + inConfig(JavaDoc)(Defaults.configSettings) ++ { + if (disableDocs) Nil + else Seq( + packageDoc in Compile := (packageDoc in JavaDoc).value, + sources in JavaDoc := { + val allJavaSources = + (target.value / "java" ** "*.java").get ++ + (sources in Compile).value.filter(_.getName.endsWith(".java")) + allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc + }, + javacOptions in JavaDoc := Seq(), + artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.13" cross CrossVersion.full), + scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") + ) + } + ) + .settings( initialCommands := """|import scala.concurrent._ |import ExecutionContext.Implicits.global diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..b789b43 --- /dev/null +++ b/build.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -e + +# Builds of tagged revisions are published to sonatype staging. + +# Travis runs a build on new revisions and on new tags, so a tagged revision is built twice. +# Builds for a tag have TRAVIS_TAG defined, which we use for identifying tagged builds. + +# sbt-dynver sets the version number from the tag +# sbt-travisci sets the Scala version from the travis job matrix + +# When a new binary incompatible Scala version becomes available, a previously released version +# can be released using that new Scala version by creating a new tag containing the Scala version +# after a hash, e.g., v1.2.3#2.13.0-M3. In this situation, the first job of the travis job +# matrix builds the release. All other jobs are stopped. Make sure that the first job uses +# the desired JVM version. + +# For normal tags that are cross-built, we release on JDK 8 for Scala 2.x +isReleaseJob() { + if [[ "$ADOPTOPENJDK" == "8" ]]; then + true + else + false + fi +} + +# For tags that define a Scala version, we pick the jobs of one Scala version (2.13.x) to do the releases +isTagScalaReleaseJob() { + if [[ "$ADOPTOPENJDK" == "8" && "$TRAVIS_SCALA_VERSION" =~ ^2\.13\.[0-9]+$ ]]; then + true + else + false + fi +} + +verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" +tagPat="^v$verPat(#$verPat)?$" + +if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then + releaseTask="ci-release" + tagScalaVer=$(echo $TRAVIS_TAG | sed s/[^#]*// | sed s/^#//) + if [[ "$tagScalaVer" == "" ]]; then + if ! isReleaseJob; then + echo "Not releasing on Java $ADOPTOPENJDK with Scala $TRAVIS_SCALA_VERSION" + exit 0 + fi + else + if isTagScalaReleaseJob; then + setTagScalaVersion='set every scalaVersion := "'$tagScalaVer'"' + else + echo "The releases for Scala $tagScalaVer are built by other jobs in the travis job matrix" + exit 0 + fi + fi +fi + +# default is +publishSigned; we cross-build with travis jobs, not sbt's crossScalaVersions +export CI_RELEASE="publishSigned" +export CI_SNAPSHOT_RELEASE="publish" + +# default is sonatypeBundleRelease, which closes and releases the staging repo +# see https://github.com/xerial/sbt-sonatype#commands +# for now, until we're confident in the new release scripts, just close the staging repo. +export CI_SONATYPE_RELEASE="; sonatypePrepare; sonatypeBundleUpload; sonatypeClose" + +sbt "$setTagScalaVersion" clean test publishLocal $releaseTask diff --git a/project/plugins.sbt b/project/plugins.sbt index 2de9ecd..6165df3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,8 +1 @@ -scalacOptions ++= (sys.props("java.specification.version") match { - // work around weird dbuild thing for JDK 12 community build; see - // https://github.com/scala/community-builds/issues/862#issuecomment-464227096 - case "12" => Seq() - case _ => Seq("-Xfatal-warnings") -}) - -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.0.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.2") From 43cb2feba74b624969e2376afcacd8c2958b6e2c Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 18 Sep 2019 01:47:05 +0200 Subject: [PATCH 171/340] Update genjavadoc-plugin to 0.14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3a2b463..5e256f6 100644 --- a/build.sbt +++ b/build.sbt @@ -131,7 +131,7 @@ lazy val root = (project in file(".")). }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.13" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.14" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ))): _* ). From fba012762a35b4778b64e850e6411253bdc7a903 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 21 Sep 2019 08:48:50 +0200 Subject: [PATCH 172/340] Update sbt-scala-module to 2.1.3 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 6165df3..b90a51e 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.2") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.3") From 07d8ba5857bebcd4ea3df1e081f5c424447c5840 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 21 Sep 2019 08:49:20 +0200 Subject: [PATCH 173/340] Update sbt to 1.3.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 080a737..8522443 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.0 +sbt.version=1.3.2 From 6eefd1829de64a53050d3a07870ae24fd517c106 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Mon, 23 Sep 2019 10:24:12 +0200 Subject: [PATCH 174/340] Update build.sh --- build.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.sh b/build.sh index b789b43..65cc465 100755 --- a/build.sh +++ b/build.sh @@ -12,9 +12,7 @@ set -e # When a new binary incompatible Scala version becomes available, a previously released version # can be released using that new Scala version by creating a new tag containing the Scala version -# after a hash, e.g., v1.2.3#2.13.0-M3. In this situation, the first job of the travis job -# matrix builds the release. All other jobs are stopped. Make sure that the first job uses -# the desired JVM version. +# after a hash, e.g., v1.2.3#2.13.0-M3. # For normal tags that are cross-built, we release on JDK 8 for Scala 2.x isReleaseJob() { From 0ea44512c9336c09ca393c5e5af89ebf14a26493 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 15 Oct 2019 00:26:06 +0200 Subject: [PATCH 175/340] Update sbt to 1.3.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 8522443..6adcdc7 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.2 +sbt.version=1.3.3 From 86e79d051355598860fb002ffdcf871d2e71ec05 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 7 Nov 2019 18:51:21 +0100 Subject: [PATCH 176/340] Update genjavadoc-plugin to 0.15 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9c58eb8..791afb2 100644 --- a/build.sbt +++ b/build.sbt @@ -127,7 +127,7 @@ lazy val scalaJava8Compat = (project in file(".")) }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.14" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.15" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ) } From 7ee5a878f4c383e22d462a61b263c1c07fb22f86 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 23 Nov 2019 23:54:32 +0100 Subject: [PATCH 177/340] Update sbt to 1.3.4 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6adcdc7..5a9ed92 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.3 +sbt.version=1.3.4 From 41c2992aab04cd05d4fa4d463c5829d93628aa1c Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Tue, 3 Dec 2019 11:38:31 +0100 Subject: [PATCH 178/340] Import travis caching config and JDK install from scala-dev --- .travis.yml | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index c8b0fa9..a1bc0f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ +version: ~> 1.0 # needed for imports + +import: scala/scala-dev:travis/default.yml + language: scala scala: @@ -9,17 +13,7 @@ env: - ADOPTOPENJDK=8 - ADOPTOPENJDK=11 -before_install: - # adding $HOME/.sdkman to cache would create an empty directory, which interferes with the initial installation - - "[[ -d $HOME/.sdkman/bin ]] || rm -rf $HOME/.sdkman/" - - curl -sL https://get.sdkman.io | bash - - echo sdkman_auto_answer=true > $HOME/.sdkman/etc/config - - source "$HOME/.sdkman/bin/sdkman-init.sh" - install: - - sdk install java $(sdk list java | grep -o "$ADOPTOPENJDK\.[0-9\.]*hs-adpt" | head -1) - - unset JAVA_HOME - - java -Xmx32m -version - git fetch --tags # get all tags for sbt-dynver script: ./build.sh @@ -28,14 +22,3 @@ notifications: email: - jason.zaugg@lightbend.com - seth.tisue@lightbend.com - -before_cache: - - rm -f $HOME/.ivy2/.sbt.ivy.lock - - find $HOME/.ivy2/cache -name "ivydata-*.properties" | xargs rm - - find $HOME/.sbt -name "*.lock" | xargs rm -cache: - directories: - - $HOME/.ivy2/cache - - $HOME/.sbt - - $HOME/.cache/coursier - - $HOME/.sdkman From 40aa8487c09a39576650b480cc26faeb6cba6366 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 14 Dec 2019 16:02:48 +0100 Subject: [PATCH 179/340] Update sbt to 1.3.5 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 5a9ed92..6624da7 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.4 +sbt.version=1.3.5 From 0956679f0e7018f829ae7459b05ec4bd852b37ac Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 27 Dec 2019 17:17:12 +0100 Subject: [PATCH 180/340] Update sbt to 1.3.6 (#173) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6624da7..00b48d9 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.5 +sbt.version=1.3.6 From 6951fc58e226185bb2beb66ab798986cc911f8fb Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 1 Jan 2020 19:06:27 +0100 Subject: [PATCH 181/340] Update junit to 4.13 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 791afb2..4d296fd 100644 --- a/build.sbt +++ b/build.sbt @@ -64,7 +64,7 @@ lazy val scalaJava8Compat = (project in file(".")) OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), - libraryDependencies += "junit" % "junit" % "4.12" % "test", + libraryDependencies += "junit" % "junit" % "4.13" % "test", libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.9" % "test", From 566d9d70ae14da402741c257b6bd3850846abac7 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 16 Jan 2020 18:20:38 +0100 Subject: [PATCH 182/340] Update sbt to 1.3.7 (#175) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 00b48d9..a82bb05 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.6 +sbt.version=1.3.7 From bbbac51cb2da0639b2cc59f6306ff2484f0470f8 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 22 Jan 2020 11:57:25 -0800 Subject: [PATCH 183/340] copyright 2020 (#176) --- NOTICE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE b/NOTICE index e4ab773..3eccb0b 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,6 @@ scala-java8-compat -Copyright (c) 2002-2019 EPFL -Copyright (c) 2011-2019 Lightbend, Inc. +Copyright (c) 2002-2020 EPFL +Copyright (c) 2011-2020 Lightbend, Inc. scala-java8-compat includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and From 75c255dda9064753aafbe109a04b57b163a5e0be Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 4 Feb 2020 02:22:22 +0100 Subject: [PATCH 184/340] Update sbt to 1.3.8 (#177) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index a82bb05..a919a9b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.7 +sbt.version=1.3.8 From 2f0fe23a656f63499794b39455867c35d075ac79 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 18 Feb 2020 14:29:41 -0800 Subject: [PATCH 185/340] bump Scala versions (2.12.8->10, 2.13.0->1) --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1bc0f5..9e57887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ language: scala scala: - 2.11.12 - - 2.12.8 - - 2.13.0 + - 2.12.10 + - 2.13.1 env: - ADOPTOPENJDK=8 @@ -20,5 +20,4 @@ script: ./build.sh notifications: email: - - jason.zaugg@lightbend.com - seth.tisue@lightbend.com From 90dbe496d54d4099a71739b4e4fde111d4a71b9a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 24 Mar 2020 01:38:27 +0100 Subject: [PATCH 186/340] Update genjavadoc-plugin to 0.16 (#180) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4d296fd..4320c4d 100644 --- a/build.sbt +++ b/build.sbt @@ -127,7 +127,7 @@ lazy val scalaJava8Compat = (project in file(".")) }, javacOptions in JavaDoc := Seq(), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.15" cross CrossVersion.full), + libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") ) } From f66ea19070983f0e89443f389878d20b9bb75922 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 31 Mar 2020 20:15:37 +0200 Subject: [PATCH 187/340] Update sbt to 1.3.9 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index a919a9b..06703e3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.8 +sbt.version=1.3.9 From 5d5dc3828e3455b81d8199c31880c4a65289acdd Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 1 Apr 2020 22:54:15 +0200 Subject: [PATCH 188/340] Update commons-lang3 to 3.10 (#181) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 4320c4d..2b30be6 100644 --- a/build.sbt +++ b/build.sbt @@ -66,7 +66,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "junit" % "junit" % "4.13" % "test", - libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.9" % "test", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.10" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", From ce3f23392ae00a0b785ff005b5bb988df4244318 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 15 Apr 2020 07:12:36 +0200 Subject: [PATCH 189/340] Update sbt to 1.3.10 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 06703e3..797e7cc 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.9 +sbt.version=1.3.10 From eb98bb0d098634b13e2721189e0c72a8e4910f93 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 15 Apr 2020 21:54:43 +0200 Subject: [PATCH 190/340] Update sbt-scala-module to 2.1.4 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index b90a51e..c4fc094 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.3") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.4") From 4f0acc6a67ed2cd83c8ce268b61dc985c3a6a216 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 16 Apr 2020 18:56:47 +0200 Subject: [PATCH 191/340] Update sbt-scala-module to 2.2.0 --- build.sbt | 2 +- project/plugins.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 2b30be6..f18c8e0 100644 --- a/build.sbt +++ b/build.sbt @@ -52,7 +52,7 @@ lazy val fnGen = (project in file("fnGen")) lazy val scalaJava8Compat = (project in file(".")) .settings(ScalaModulePlugin.scalaModuleSettings) - .settings(ScalaModulePlugin.scalaModuleSettingsJVM) + .settings(ScalaModulePlugin.scalaModuleOsgiSettings) .settings(commonSettings) .settings( name := "scala-java8-compat" diff --git a/project/plugins.sbt b/project/plugins.sbt index c4fc094..637b027 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.1.4") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.0") From 4bd63b257e540efd43a96b86f5ca1977a32fc680 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 30 Apr 2020 10:38:04 -0700 Subject: [PATCH 192/340] add Scaladoc link to readme fixes #62 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ca6acc..81e621f 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ A Java 8 compatibility kit for Scala. The API is currently still experimental: we do not yet guarantee source or binary compatibility with future releases. +Scaladoc is [here](https://javadoc.io/doc/org.scala-lang.modules/scala-java8-compat_2.13/latest/index.html). + ## Functional Interfaces for Scala functions A set of [Functional Interfaces](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) @@ -283,5 +285,3 @@ import scala.concurrent.duration.FiniteDuration; DurationConverters.toScala(Duration.of(5, ChronoUnit.SECONDS)); DurationConverters.toJava(FiniteDuration.create(5, TimeUnit.SECONDS)); ``` - - From 4a3183e690134b0b262ac93a4365e6eb00b27675 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 30 Apr 2020 10:39:33 -0700 Subject: [PATCH 193/340] oops --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81e621f..55e15ec 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A Java 8 compatibility kit for Scala. The API is currently still experimental: we do not yet guarantee source or binary compatibility with future releases. -Scaladoc is [here](https://javadoc.io/doc/org.scala-lang.modules/scala-java8-compat_2.13/latest/index.html). +Javadoc is [here](https://javadoc.io/doc/org.scala-lang.modules/scala-java8-compat_2.13/latest/index.html). ## Functional Interfaces for Scala functions From 8c5dbd4bb76029b526336a69fb62dd94fa0e6102 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sun, 31 May 2020 04:53:43 +0200 Subject: [PATCH 194/340] Update sbt to 1.3.12 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 797e7cc..654fe70 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.10 +sbt.version=1.3.12 From de236a481972d236172f4a1b2ffbd64417903096 Mon Sep 17 00:00:00 2001 From: "Will Sargent (eero)" <52975802+will-sargent-eero@users.noreply.github.com> Date: Thu, 2 Jul 2020 13:59:35 -0700 Subject: [PATCH 195/340] Update README.md Make it clearer what the concurrency package does --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 55e15ec..e21f48b 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,8 @@ class Example { ## Converters between `scala.concurrent` and `java.util.concurrent` +Conversion between Java's concurrency primitives (`CompletionStage` and `CompletableFuture`) and the Scala concurrency primitives (`Promise` and `Future`) is enabled with `scala.compat.java8.FutureConverters` singleton object: + - [API](src/main/scala/scala/compat/java8/FutureConverters.scala) - [Test Cases](src/test/java/scala/compat/java8/FutureConvertersTest.java) From cfd8a633acd2e80f1d916128d41660c571f4f32c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 1 Aug 2020 20:36:54 +0200 Subject: [PATCH 196/340] Update commons-lang3 to 3.11 (#190) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index f18c8e0..854c90c 100644 --- a/build.sbt +++ b/build.sbt @@ -66,7 +66,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "junit" % "junit" % "4.13" % "test", - libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.10" % "test", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.11" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", From 5657094b4a14fc0f16a25b07d4ac13108851263e Mon Sep 17 00:00:00 2001 From: "Sean C. Sullivan" Date: Sun, 30 Aug 2020 11:30:38 -0700 Subject: [PATCH 197/340] Scala 2.13.3, Scala 2.12.12 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9e57887..bcf2b8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ language: scala scala: - 2.11.12 - - 2.12.10 - - 2.13.1 + - 2.12.12 + - 2.13.3 env: - ADOPTOPENJDK=8 From 98e1eba634443096bdb5aa5c92619ae48e6c8439 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 31 Aug 2020 03:47:03 +0200 Subject: [PATCH 198/340] Update sbt to 1.3.13 (#188) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 654fe70..0837f7a 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.12 +sbt.version=1.3.13 From 43fdd2d2ebefea7acfab35063ecd3e3bbc90c73a Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 9 Sep 2020 05:57:55 +0200 Subject: [PATCH 199/340] Update sbt-scala-module to 2.2.1 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 637b027..e2bd0d1 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.1") From 38a340e03bf13749421c1b1475bff47dedc4f091 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 1 Oct 2020 03:35:34 +0200 Subject: [PATCH 200/340] Update sbt-scala-module to 2.2.2 (#193) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index e2bd0d1..c3f0c93 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.1") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.2") From 6992c30fe49faf903dfdc18ab040cde09b05b053 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 11 Oct 2020 22:20:31 +0200 Subject: [PATCH 201/340] Update junit to 4.13.1 (#195) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 854c90c..816cc65 100644 --- a/build.sbt +++ b/build.sbt @@ -64,7 +64,7 @@ lazy val scalaJava8Compat = (project in file(".")) OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), - libraryDependencies += "junit" % "junit" % "4.13" % "test", + libraryDependencies += "junit" % "junit" % "4.13.1" % "test", libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.11" % "test", From 3390a81c1453b4977c8e57aae9243349aa4aee3c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 15 Oct 2020 06:05:27 +0200 Subject: [PATCH 202/340] Update sbt to 1.4.0 (#194) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 0837f7a..6db9842 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.13 +sbt.version=1.4.0 From 9be98406360d98d582b8c7fd79d4108dcadea53a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 20 Oct 2020 04:36:49 +0200 Subject: [PATCH 203/340] Update sbt to 1.4.1 (#196) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6db9842..08e4d79 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.0 +sbt.version=1.4.1 From 8266986db9ad0a05738b57546b8a09bbcdf8c145 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 2 Nov 2020 23:55:01 +0100 Subject: [PATCH 204/340] Update sbt to 1.4.2 (#198) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 08e4d79..c19c768 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.1 +sbt.version=1.4.2 From af0c17dbc8dd2ab42c3b7190beee174c5932da9d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 10 Nov 2020 23:31:29 +0100 Subject: [PATCH 205/340] Update sbt-scala-module to 2.2.3 (#197) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index c3f0c93..81fac90 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.2") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.3") From 27b208e1d0c381705b6615c3082eac39c78bc212 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 28 Nov 2020 18:04:37 +0100 Subject: [PATCH 206/340] Update sbt to 1.4.4 (#201) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index c19c768..7de0a93 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.2 +sbt.version=1.4.4 From c344af4a3e6409070e87087eadd21c287ad973cc Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 18 Dec 2020 20:08:30 +0100 Subject: [PATCH 207/340] Update sbt to 1.4.5 (#202) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 7de0a93..c06db1b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.4 +sbt.version=1.4.5 From 584577ef21255e458001b94e531ca8eeec295af9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 6 Jan 2021 01:25:51 +0100 Subject: [PATCH 208/340] Update sbt to 1.4.6 (#203) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index c06db1b..d91c272 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.5 +sbt.version=1.4.6 From baefe65a8806155e9e984a5f9b87ab8e6f1e2f40 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 26 Jan 2021 13:50:12 -0800 Subject: [PATCH 209/340] copyright 2021 (#205) --- NOTICE | 4 ++-- project/CodeGen.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NOTICE b/NOTICE index 3eccb0b..a076f57 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,6 @@ scala-java8-compat -Copyright (c) 2002-2020 EPFL -Copyright (c) 2011-2020 Lightbend, Inc. +Copyright (c) 2002-2021 EPFL +Copyright (c) 2011-2021 Lightbend, Inc. scala-java8-compat includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and diff --git a/project/CodeGen.scala b/project/CodeGen.scala index b3f3f11..bb3a37e 100644 --- a/project/CodeGen.scala +++ b/project/CodeGen.scala @@ -296,7 +296,7 @@ object CodeGen { private val copyright = """ |/* - | * Copyright (C) 2012-2016 Lightbend Inc. + | * Copyright (C) Lightbend Inc. | */""".stripMargin.trim private def function0SpecMethods = { From aa38b470e151043025125628872e3aa10eb3225d Mon Sep 17 00:00:00 2001 From: "Sean C. Sullivan" Date: Thu, 31 Dec 2020 20:11:43 -0800 Subject: [PATCH 210/340] Scala 2.13.4 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bcf2b8d..a0b9fd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ language: scala scala: - 2.11.12 - 2.12.12 - - 2.13.3 + - 2.13.4 env: - ADOPTOPENJDK=8 From b9c9e91c7c2785c73c3ae7e0b096c82a3c109390 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 28 Jan 2021 19:38:52 -0800 Subject: [PATCH 211/340] attempt to avoid weird Javadoc heisenerror --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 816cc65..0396985 100644 --- a/build.sbt +++ b/build.sbt @@ -125,7 +125,7 @@ lazy val scalaJava8Compat = (project in file(".")) (sources in Compile).value.filter(_.getName.endsWith(".java")) allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc }, - javacOptions in JavaDoc := Seq(), + javacOptions in JavaDoc := Seq("-Xdoclint:none"), artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full), scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") From d1013f8cc7832a48d0fd594d88320ad6a137a5f6 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 7 Feb 2021 22:08:49 +0100 Subject: [PATCH 212/340] Update sbt to 1.4.7 (#206) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index d91c272..0b2e09c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.6 +sbt.version=1.4.7 From 44ed917db91a739d47dba5210e2a757d34efcfe7 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 7 Feb 2021 22:08:59 +0100 Subject: [PATCH 213/340] Update sbt-scala-module to 2.2.4 (#207) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 81fac90..53db5d3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.3") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") From 59594a9688e4a7619387aadcb7b79e150a5c1de8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 4 Mar 2021 18:35:52 +0100 Subject: [PATCH 214/340] Update junit to 4.13.2 (#208) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0396985..0b64ac4 100644 --- a/build.sbt +++ b/build.sbt @@ -64,7 +64,7 @@ lazy val scalaJava8Compat = (project in file(".")) OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), - libraryDependencies += "junit" % "junit" % "4.13.1" % "test", + libraryDependencies += "junit" % "junit" % "4.13.2" % "test", libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.11" % "test", From 92c24cfe1bfa8093ed5a6eeaa1ca10d4cc75f9f9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 4 Mar 2021 18:36:01 +0100 Subject: [PATCH 215/340] Update commons-lang3 to 3.12.0 (#209) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0b64ac4..cb6a47c 100644 --- a/build.sbt +++ b/build.sbt @@ -66,7 +66,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "junit" % "junit" % "4.13.2" % "test", - libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.11" % "test", + libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.12.0" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", From 82be2fa7960c2e4eaad720cbb8e4503ef1a3f80d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Fri, 5 Mar 2021 09:54:18 -0800 Subject: [PATCH 216/340] declare versionScheme and enable MiMa fixes #210 --- build.sbt | 8 +++++++- build.sh | 2 +- project/plugins.sbt | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index cb6a47c..71a5505 100644 --- a/build.sbt +++ b/build.sbt @@ -18,6 +18,9 @@ def osgiExport(scalaVersion: String, version: String) = { }) ++ Seq(s"scala.compat.java8.*;version=${version}") } +ThisBuild / versionScheme := Some("early-semver") +ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible + lazy val commonSettings = Seq( scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked"), @@ -70,7 +73,10 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - scalaModuleMimaPreviousVersion := None, + // we're still in 0.x land so we could choose to break bincompat, + // but let's at least be aware when we're doing it. also we should + // think about going 1.0, it's been a while + scalaModuleMimaPreviousVersion := Some("0.9.1"), testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), diff --git a/build.sh b/build.sh index 65cc465..8dcf234 100755 --- a/build.sh +++ b/build.sh @@ -62,4 +62,4 @@ export CI_SNAPSHOT_RELEASE="publish" # for now, until we're confident in the new release scripts, just close the staging repo. export CI_SONATYPE_RELEASE="; sonatypePrepare; sonatypeBundleUpload; sonatypeClose" -sbt "$setTagScalaVersion" clean test publishLocal $releaseTask +sbt "$setTagScalaVersion" clean test versionPolicyCheck publishLocal $releaseTask diff --git a/project/plugins.sbt b/project/plugins.sbt index 53db5d3..32698b2 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1,2 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") +addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0-RC5") From 18042c9cae9717a1b11daea136fe861b76d008d9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 8 Mar 2021 07:01:18 +0100 Subject: [PATCH 217/340] Update sbt to 1.4.8 (#212) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 0b2e09c..b5ef6ff 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.7 +sbt.version=1.4.8 From f3d7e70b40fde7dc0d0bedb8ea696d6b7b7f659c Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 9 Mar 2021 11:17:13 -0800 Subject: [PATCH 218/340] upgrade to latest Scala versions (2.12.13, 2.13.5) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a0b9fd8..d5108f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ language: scala scala: - 2.11.12 - - 2.12.12 - - 2.13.4 + - 2.12.13 + - 2.13.5 env: - ADOPTOPENJDK=8 From 8e2b88eb672b0fe9080dfdcd0ce41c880a138c9d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 13 Mar 2021 11:54:37 -0800 Subject: [PATCH 219/340] forcibly make MiMa green --- build.sbt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build.sbt b/build.sbt index 71a5505..a7151a9 100644 --- a/build.sbt +++ b/build.sbt @@ -78,6 +78,19 @@ lazy val scalaJava8Compat = (project in file(".")) // think about going 1.0, it's been a while scalaModuleMimaPreviousVersion := Some("0.9.1"), + mimaBinaryIssueFilters ++= { + import com.typesafe.tools.mima.core._, ProblemFilters._ + Seq( + // bah + exclude[IncompatibleSignatureProblem]("*"), + // mysterious -- see scala/scala-java8-compat#211 + exclude[DirectMissingMethodProblem ]("scala.compat.java8.Priority1FunctionConverters.enrichAsJavaIntFunction"), + exclude[ReversedMissingMethodProblem]("scala.compat.java8.Priority1FunctionConverters.enrichAsJavaIntFunction"), + exclude[DirectMissingMethodProblem ]("scala.compat.java8.FunctionConverters.package.enrichAsJavaIntFunction" ), + exclude[ReversedMissingMethodProblem]("scala.compat.java8.FunctionConverters.package.enrichAsJavaIntFunction" ), + ) + }, + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), (sourceGenerators in Compile) += Def.task { From d2dafa609dc6b7de434c05037bdcc939cf9b0337 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 13 Mar 2021 21:08:19 +0100 Subject: [PATCH 220/340] Update sbt to 1.4.9 (#214) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index b5ef6ff..dbae93b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.8 +sbt.version=1.4.9 From 3375e8e8bfdb139f762ec4b6a2207a9c54f22a11 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 23 Mar 2021 07:28:23 -0700 Subject: [PATCH 221/340] sbt build cleanup: use slash syntax --- build.sbt | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/build.sbt b/build.sbt index a7151a9..3d1ab7a 100644 --- a/build.sbt +++ b/build.sbt @@ -24,8 +24,8 @@ ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible lazy val commonSettings = Seq( scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked"), - unmanagedSourceDirectories in Compile ++= { - (unmanagedSourceDirectories in Compile).value.flatMap { dir => + Compile / unmanagedSourceDirectories ++= { + (Compile / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) @@ -34,8 +34,8 @@ lazy val commonSettings = Seq( } }, - unmanagedSourceDirectories in Test ++= { - (unmanagedSourceDirectories in Test).value.flatMap { dir => + Test / unmanagedSourceDirectories ++= { + (Test / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) @@ -48,7 +48,7 @@ lazy val commonSettings = Seq( lazy val fnGen = (project in file("fnGen")) .settings(commonSettings) .settings( - fork in run := true, // Needed if you run this project directly + run / fork := true, // Needed if you run this project directly libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value ) @@ -93,19 +93,19 @@ lazy val scalaJava8Compat = (project in file(".")) testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), - (sourceGenerators in Compile) += Def.task { - val out = (sourceManaged in Compile).value + (Compile / sourceGenerators) += Def.task { + val out = (Compile / sourceManaged).value if (!out.exists) IO.createDirectory(out) val canon = out.getCanonicalPath val args = (new File(canon, "FunctionConverters.scala")).toString :: Nil - val runTarget = (mainClass in Compile in fnGen).value getOrElse "No main class defined for function conversion generator" - val classPath = (fullClasspath in Compile in fnGen).value + val runTarget = (fnGen / Compile / mainClass).value getOrElse "No main class defined for function conversion generator" + val classPath = (fnGen / Compile / fullClasspath).value runner.value.run(runTarget, classPath.files, args, streams.value.log) (out ** "*.scala").get }.taskValue, - sourceGenerators in Compile += Def.task { - val dir = (sourceManaged in Compile).value + Compile / sourceGenerators += Def.task { + val dir = (Compile / sourceManaged).value val write = jwrite(dir) _ if(scalaVersion.value.startsWith("2.11.")) { Seq(write("JFunction", CodeGen.factory)) ++ @@ -118,8 +118,8 @@ lazy val scalaJava8Compat = (project in file(".")) } else CodeGen.create212.map(write.tupled) }.taskValue, - sourceGenerators in Test += Def.task { - Seq(jwrite((sourceManaged in Test).value)("TestApi", CodeGen.testApi)) + Test / sourceGenerators += Def.task { + Seq(jwrite((Test / sourceManaged).value)("TestApi", CodeGen.testApi)) }.taskValue, initialize := { @@ -131,23 +131,23 @@ lazy val scalaJava8Compat = (project in file(".")) sys.error("Java 8 or higher is required for this project.") }, - publishArtifact in packageDoc := !disableDocs + packageDoc / publishArtifact := !disableDocs ) .settings( inConfig(JavaDoc)(Defaults.configSettings) ++ { if (disableDocs) Nil else Seq( - packageDoc in Compile := (packageDoc in JavaDoc).value, - sources in JavaDoc := { + Compile / packageDoc := (JavaDoc / packageDoc).value, + JavaDoc / sources := { val allJavaSources = (target.value / "java" ** "*.java").get ++ - (sources in Compile).value.filter(_.getName.endsWith(".java")) + (Compile / sources).value.filter(_.getName.endsWith(".java")) allJavaSources.filterNot(_.getName.contains("FuturesConvertersImpl.java")) // this file triggers bugs in genjavadoc }, - javacOptions in JavaDoc := Seq("-Xdoclint:none"), - artifactName in packageDoc in JavaDoc := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), + JavaDoc / javacOptions := Seq("-Xdoclint:none"), + JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full), - scalacOptions in Compile += "-P:genjavadoc:out=" + (target.value / "java") + Compile / scalacOptions += "-P:genjavadoc:out=" + (target.value / "java") ) } ) From 7e706e3e862dcac283b6a9473bad904f3646f820 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Mar 2021 16:48:01 -0700 Subject: [PATCH 222/340] avoid deprecation warning --- fnGen/WrapFnGen.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala index c3e2e86..794c104 100644 --- a/fnGen/WrapFnGen.scala +++ b/fnGen/WrapFnGen.scala @@ -143,7 +143,7 @@ object WrapFnGen { private def buildWrappersViaReflection: Seq[SamConversionCode] = { - val pack: Symbol = rootMirror.getPackageIfDefined(TermName("java.util.function")) + val pack: Symbol = rootMirror.getPackageIfDefined("java.util.function") case class Jfn(iface: Symbol, sam: Symbol) { lazy val genericCount = iface.typeParams.length From 4732e78098be6cce7cfd8dc60a54ba9dfc3d2c3e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Mar 2021 16:48:20 -0700 Subject: [PATCH 223/340] code improvement (for Scala 3, but good on 2 also) --- .../scala/compat/java8/StreamConverters.scala | 2 +- .../converterImpl/AccumulatorConverters.scala | 24 ++-- .../scala/compat/java8/OptionConverters.scala | 57 +++++---- .../java8/PrimitiveIteratorConversions.scala | 115 +++++++++--------- 4 files changed, 106 insertions(+), 92 deletions(-) diff --git a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala index 8adea5f..47bfa05 100644 --- a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala @@ -21,7 +21,7 @@ import scala.collection.{IterableOnce, Stepper, StepperShape} import scala.compat.java8.converterImpl._ import scala.jdk.CollectionConverters._ import scala.jdk._ -import scala.language.{higherKinds, implicitConversions} +import scala.language.implicitConversions /** Defines extension methods to create Java Streams for Scala collections, available through * [[scala.compat.java8.StreamConverters]]. diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala index 4ff943a..b2e7e2b 100644 --- a/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -15,18 +15,26 @@ package scala.compat.java8.converterImpl import scala.language.implicitConversions trait Priority3AccumulatorConverters { - implicit def collectionCanAccumulate[A](underlying: IterableOnce[A]) = new CollectionCanAccumulate[A](underlying) + implicit def collectionCanAccumulate[A](underlying: IterableOnce[A]): CollectionCanAccumulate[A] = + new CollectionCanAccumulate[A](underlying) } trait Priority2AccumulatorConverters extends Priority3AccumulatorConverters { - implicit def accumulateDoubleCollection(underlying: IterableOnce[Double]) = new AccumulateDoubleCollection(underlying) - implicit def accumulateIntCollection(underlying: IterableOnce[Int]) = new AccumulateIntCollection(underlying) - implicit def accumulateLongCollection(underlying: IterableOnce[Long]) = new AccumulateLongCollection(underlying) - implicit def accumulateAnyArray[A](underlying: Array[A]) = new AccumulateAnyArray(underlying) + implicit def accumulateDoubleCollection(underlying: IterableOnce[Double]): AccumulateDoubleCollection = + new AccumulateDoubleCollection(underlying) + implicit def accumulateIntCollection(underlying: IterableOnce[Int]): AccumulateIntCollection = + new AccumulateIntCollection(underlying) + implicit def accumulateLongCollection(underlying: IterableOnce[Long]): AccumulateLongCollection = + new AccumulateLongCollection(underlying) + implicit def accumulateAnyArray[A](underlying: Array[A]): AccumulateAnyArray[A] = + new AccumulateAnyArray(underlying) } trait Priority1AccumulatorConverters extends Priority2AccumulatorConverters { - implicit def accumulateDoubleArray(underlying: Array[Double]) = new AccumulateDoubleArray(underlying) - implicit def accumulateIntArray(underlying: Array[Int]) = new AccumulateIntArray(underlying) - implicit def accumulateLongArray(underlying: Array[Long]) = new AccumulateLongArray(underlying) + implicit def accumulateDoubleArray(underlying: Array[Double]): AccumulateDoubleArray = + new AccumulateDoubleArray(underlying) + implicit def accumulateIntArray(underlying: Array[Int]): AccumulateIntArray = + new AccumulateIntArray(underlying) + implicit def accumulateLongArray(underlying: Array[Long]): AccumulateLongArray = + new AccumulateLongArray(underlying) } diff --git a/src/main/scala/scala/compat/java8/OptionConverters.scala b/src/main/scala/scala/compat/java8/OptionConverters.scala index 49e06c2..64572dc 100644 --- a/src/main/scala/scala/compat/java8/OptionConverters.scala +++ b/src/main/scala/scala/compat/java8/OptionConverters.scala @@ -58,30 +58,33 @@ object OptionConverters { /** Converts from `Option` to a manually specialized variant `That` */ def fromScala(o: Option[A]): That } - + /** Implementation of creation of `OptionalDouble` from `Option[Double]` or `Optional[Double]`*/ - implicit val specializer_OptionalDouble = new SpecializerOfOptions[Double, OptionalDouble] { - /** Creates an `OptionalDouble` from `Optional[Double]` */ - def fromJava(o: Optional[Double]): OptionalDouble = if (o.isPresent) OptionalDouble.of(o.get) else OptionalDouble.empty - /** Creates an `OptionalDouble` from `Option[Double]` */ - def fromScala(o: Option[Double]): OptionalDouble = o match { case Some(d) => OptionalDouble.of(d); case _ => OptionalDouble.empty } - } - + implicit val specializer_OptionalDouble: SpecializerOfOptions[Double, OptionalDouble] = + new SpecializerOfOptions[Double, OptionalDouble] { + /** Creates an `OptionalDouble` from `Optional[Double]` */ + def fromJava(o: Optional[Double]): OptionalDouble = if (o.isPresent) OptionalDouble.of(o.get) else OptionalDouble.empty + /** Creates an `OptionalDouble` from `Option[Double]` */ + def fromScala(o: Option[Double]): OptionalDouble = o match { case Some(d) => OptionalDouble.of(d); case _ => OptionalDouble.empty } + } + /** Implementation of creation of `OptionalInt` from `Option[Int]` or `Optional[Int]`*/ - implicit val specializer_OptionalInt = new SpecializerOfOptions[Int, OptionalInt] { - /** Creates an `OptionalInt` from `Optional[Int]` */ - def fromJava(o: Optional[Int]): OptionalInt = if (o.isPresent) OptionalInt.of(o.get) else OptionalInt.empty - /** Creates an `OptionalInt` from `Option[Int]` */ - def fromScala(o: Option[Int]): OptionalInt = o match { case Some(d) => OptionalInt.of(d); case _ => OptionalInt.empty } - } - + implicit val specializer_OptionalInt: SpecializerOfOptions[Int, OptionalInt] = + new SpecializerOfOptions[Int, OptionalInt] { + /** Creates an `OptionalInt` from `Optional[Int]` */ + def fromJava(o: Optional[Int]): OptionalInt = if (o.isPresent) OptionalInt.of(o.get) else OptionalInt.empty + /** Creates an `OptionalInt` from `Option[Int]` */ + def fromScala(o: Option[Int]): OptionalInt = o match { case Some(d) => OptionalInt.of(d); case _ => OptionalInt.empty } + } + /** Implementation of creation of `OptionalLong` from `Option[Long]` or `Optional[Long]`*/ - implicit val specializer_OptionalLong = new SpecializerOfOptions[Long, OptionalLong] { - /** Creates an `OptionalLong` from `Optional[Long]` */ - def fromJava(o: Optional[Long]): OptionalLong = if (o.isPresent) OptionalLong.of(o.get) else OptionalLong.empty - /** Creates an `OptionalLong` from `Option[Long]` */ - def fromScala(o: Option[Long]): OptionalLong = o match { case Some(d) => OptionalLong.of(d); case _ => OptionalLong.empty } - } + implicit val specializer_OptionalLong: SpecializerOfOptions[Long, OptionalLong] = + new SpecializerOfOptions[Long, OptionalLong] { + /** Creates an `OptionalLong` from `Optional[Long]` */ + def fromJava(o: Optional[Long]): OptionalLong = if (o.isPresent) OptionalLong.of(o.get) else OptionalLong.empty + /** Creates an `OptionalLong` from `Option[Long]` */ + def fromScala(o: Option[Long]): OptionalLong = o match { case Some(d) => OptionalLong.of(d); case _ => OptionalLong.empty } + } /** Provides conversions from `java.util.Optional` to Scala `Option` or primitive `java.util.Optional` types */ implicit class RichOptionalGeneric[A](val underlying: java.util.Optional[A]) extends AnyVal { @@ -90,7 +93,7 @@ object OptionConverters { /** Create a specialized primitive variant of this generic `Optional`, if an appropriate one exists */ def asPrimitive[That](implicit specOp: SpecializerOfOptions[A, That]): That = specOp.fromJava(underlying) } - + /** Provides conversions from `scala.Option` to Java `Optional` types, either generic or primitive */ implicit class RichOptionForJava8[A](val underlying: Option[A]) extends AnyVal { /** Create a `java.util.Optional` version of this `Option` (not specialized) */ @@ -98,7 +101,7 @@ object OptionConverters { /** Create a specialized primitive `java.util.Optional` type, if an appropriate one exists */ def asPrimitive[That](implicit specOp: SpecializerOfOptions[A, That]): That = specOp.fromScala(underlying) } - + /** Provides conversions from `java.util.OptionalDouble` to the generic `Optional` and Scala `Option` */ implicit class RichOptionalDouble(val underlying: OptionalDouble) extends AnyVal { /** Create a `scala.Option` version of this `OptionalDouble` */ @@ -106,7 +109,7 @@ object OptionConverters { /** Create a generic `java.util.Optional` version of this `OptionalDouble` */ def asGeneric: Optional[Double] = if (underlying.isPresent) Optional.of(underlying.getAsDouble) else Optional.empty[Double] } - + /** Provides conversions from `java.util.OptionalInt` to the generic `Optional` and Scala `Option` */ implicit class RichOptionalInt(val underlying: OptionalInt) extends AnyVal { /** Create a `scala.Option` version of this `OptionalInt` */ @@ -114,7 +117,7 @@ object OptionConverters { /** Create a generic `java.util.Optional` version of this `OptionalInt` */ def asGeneric: Optional[Int] = if (underlying.isPresent) Optional.of(underlying.getAsInt) else Optional.empty[Int] } - + /** Provides conversions from `java.util.OptionalLong` to the generic `Optional` and Scala `Option` */ implicit class RichOptionalLong(val underlying: OptionalLong) extends AnyVal { /** Create a `scala.Option` version of this `OptionalLong` */ @@ -122,10 +125,10 @@ object OptionConverters { /** Create a generic `java.util.Optional` version of this `OptionalLong` */ def asGeneric: Optional[Long] = if (underlying.isPresent) Optional.of(underlying.getAsLong) else Optional.empty[Long] } - + /** Conversion from Scala `Option` to Java `Optional` without using implicits, for convenient use from Java. */ final def toJava[A](o: Option[A]): Optional[A] = o match { case Some(a) => Optional.ofNullable(a); case _ => Optional.empty[A] } - + /** Conversion from Java `Optional` to Scala `Option` without using implicits, for convenient use from Java */ final def toScala[A](o: Optional[A]): Option[A] = if (o.isPresent) Some(o.get) else None diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index d0abb4d..20400b4 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -39,76 +39,79 @@ object PrimitiveIteratorConverters { /** Packages a Scala `Iterator` to a manually specialized Java variant `That` */ def fromScala(it: Iterator[A]): That } - + /** Implementation of wrapping of `java.util.Iterator[Double]` or `scala.collection.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ - implicit val specializer_PrimitiveIteratorDouble = new SpecializerOfIterators[Double, PrimitiveIterator.OfDouble] { - /** Packages a `java.util.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ - def fromJava(it: JIterator[Double]): PrimitiveIterator.OfDouble = - new wrappers.IteratorPrimitiveDoubleWrapper(it.asInstanceOf[JIterator[java.lang.Double]]) - - /** Packages a `scala.collection.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ - def fromScala(it: Iterator[Double]): PrimitiveIterator.OfDouble = new PrimitiveIterator.OfDouble { - def hasNext = it.hasNext - override def next() = it.next().asInstanceOf[java.lang.Double] - def nextDouble() = it.next() - override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { - while (it.hasNext) c.accept(it.next()) - } - override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { - while (it.hasNext) c.accept(it.next()) + implicit val specializer_PrimitiveIteratorDouble: SpecializerOfIterators[Double, PrimitiveIterator.OfDouble] = + new SpecializerOfIterators[Double, PrimitiveIterator.OfDouble] { + /** Packages a `java.util.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ + def fromJava(it: JIterator[Double]): PrimitiveIterator.OfDouble = + new wrappers.IteratorPrimitiveDoubleWrapper(it.asInstanceOf[JIterator[java.lang.Double]]) + + /** Packages a `scala.collection.Iterator[Double]` as a `java.util.PrimitiveIterator.OfDouble` */ + def fromScala(it: Iterator[Double]): PrimitiveIterator.OfDouble = new PrimitiveIterator.OfDouble { + def hasNext = it.hasNext + override def next() = it.next().asInstanceOf[java.lang.Double] + def nextDouble() = it.next() + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Double]): Unit = { + while (it.hasNext) c.accept(it.next()) + } + override def forEachRemaining(c: java.util.function.DoubleConsumer): Unit = { + while (it.hasNext) c.accept(it.next()) + } } } - } - + /** Implementation of wrapping of `java.util.Iterator[Int]` or `scala.collection.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ - implicit val specializer_PrimitiveIteratorInt = new SpecializerOfIterators[Int, PrimitiveIterator.OfInt] { - /** Packages a `java.util.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ - def fromJava(it: JIterator[Int]): PrimitiveIterator.OfInt = - new wrappers.IteratorPrimitiveIntWrapper(it.asInstanceOf[JIterator[java.lang.Integer]]) - - /** Packages a `scala.collection.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ - def fromScala(it: Iterator[Int]): PrimitiveIterator.OfInt = new PrimitiveIterator.OfInt { - def hasNext = it.hasNext - override def next() = it.next().asInstanceOf[java.lang.Integer] - def nextInt() = it.next() - override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { - while (it.hasNext) c.accept(it.next()) - } - override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { - while (it.hasNext) c.accept(it.next()) + implicit val specializer_PrimitiveIteratorInt: SpecializerOfIterators[Int, PrimitiveIterator.OfInt] = + new SpecializerOfIterators[Int, PrimitiveIterator.OfInt] { + /** Packages a `java.util.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ + def fromJava(it: JIterator[Int]): PrimitiveIterator.OfInt = + new wrappers.IteratorPrimitiveIntWrapper(it.asInstanceOf[JIterator[java.lang.Integer]]) + + /** Packages a `scala.collection.Iterator[Int]` as a `java.util.PrimitiveIterator.OfInt` */ + def fromScala(it: Iterator[Int]): PrimitiveIterator.OfInt = new PrimitiveIterator.OfInt { + def hasNext = it.hasNext + override def next() = it.next().asInstanceOf[java.lang.Integer] + def nextInt() = it.next() + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Integer]): Unit = { + while (it.hasNext) c.accept(it.next()) + } + override def forEachRemaining(c: java.util.function.IntConsumer): Unit = { + while (it.hasNext) c.accept(it.next()) + } } } - } - + /** Implementation of wrapping of `java.util.Iterator[Long]` or `scala.collection.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ - implicit val specializer_PrimitiveIteratorLong = new SpecializerOfIterators[Long, PrimitiveIterator.OfLong] { - /** Packages a `java.util.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ - def fromJava(it: JIterator[Long]): PrimitiveIterator.OfLong = - new wrappers.IteratorPrimitiveLongWrapper(it.asInstanceOf[JIterator[java.lang.Long]]) - - /** Packages a `scala.collection.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ - def fromScala(it: Iterator[Long]): PrimitiveIterator.OfLong = new PrimitiveIterator.OfLong { - def hasNext = it.hasNext - override def next() = it.next().asInstanceOf[java.lang.Long] - def nextLong() = it.next() - override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } - override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { - while (it.hasNext) c.accept(it.next()) - } - override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { - while (it.hasNext) c.accept(it.next()) + implicit val specializer_PrimitiveIteratorLong: SpecializerOfIterators[Long, PrimitiveIterator.OfLong] = + new SpecializerOfIterators[Long, PrimitiveIterator.OfLong] { + /** Packages a `java.util.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ + def fromJava(it: JIterator[Long]): PrimitiveIterator.OfLong = + new wrappers.IteratorPrimitiveLongWrapper(it.asInstanceOf[JIterator[java.lang.Long]]) + + /** Packages a `scala.collection.Iterator[Long]` as a `java.util.PrimitiveIterator.OfLong` */ + def fromScala(it: Iterator[Long]): PrimitiveIterator.OfLong = new PrimitiveIterator.OfLong { + def hasNext = it.hasNext + override def next() = it.next().asInstanceOf[java.lang.Long] + def nextLong() = it.next() + override def remove(): Unit = { throw new UnsupportedOperationException("remove on scala.collection.Iterator") } + override def forEachRemaining(c: java.util.function.Consumer[_ >: java.lang.Long]): Unit = { + while (it.hasNext) c.accept(it.next()) + } + override def forEachRemaining(c: java.util.function.LongConsumer): Unit = { + while (it.hasNext) c.accept(it.next()) + } } } - } - + /** Provides conversions from Java `Iterator` to manually specialized `PrimitiveIterator` variants, when available */ implicit final class RichJavaIteratorToPrimitives[A](private val underlying: JIterator[A]) extends AnyVal { /** Wraps this `java.util.Iterator` as a manually specialized variant, if possible */ def asPrimitive[That](implicit specOp: SpecializerOfIterators[A, That]): That = specOp.fromJava(underlying) } - + /** Provides conversions from Scala `Iterator` to manually specialized `PrimitiveIterator` variants, when available */ implicit final class RichIteratorToPrimitives[A](private val underlying: Iterator[A]) extends AnyVal { /** Wraps this `scala.collection.Iterator` as a manually specialized `java.util.PrimitiveIterator` variant, if possible */ From d26adbe3672fc86b5f62de91fc5d8849abccad5a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 23 Mar 2021 07:28:11 -0700 Subject: [PATCH 224/340] add Scala 3 to crossbuild fixes #200 --- .travis.yml | 1 + build.sbt | 29 +++++++++++++++++++---------- project/plugins.sbt | 1 + 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index d5108f1..0a3363c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ import: scala/scala-dev:travis/default.yml language: scala scala: + - 3.0.0-RC1 - 2.11.12 - 2.12.13 - 2.13.5 diff --git a/build.sbt b/build.sbt index 3d1ab7a..d081181 100644 --- a/build.sbt +++ b/build.sbt @@ -27,9 +27,9 @@ lazy val commonSettings = Seq( Compile / unmanagedSourceDirectories ++= { (Compile / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) - case _ => Seq(file(dir.getPath ++ "-2.13-")) + case Some((2, 12)) => Seq(file(dir.getPath ++ "-2.13-")) + case _ => Seq(file(dir.getPath ++ "-2.13+")) } } }, @@ -37,9 +37,9 @@ lazy val commonSettings = Seq( Test / unmanagedSourceDirectories ++= { (Test / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, 13)) => Seq(file(dir.getPath ++ "-2.13+")) case Some((2, 11)) => Seq(file(dir.getPath ++ "-2.13-"), file(dir.getPath ++ "-2.11")) - case _ => Seq(file(dir.getPath ++ "-2.13-")) + case Some((2, 12)) => Seq(file(dir.getPath ++ "-2.13-")) + case _ => Seq(file(dir.getPath ++ "-2.13+")) } } }, @@ -48,6 +48,8 @@ lazy val commonSettings = Seq( lazy val fnGen = (project in file("fnGen")) .settings(commonSettings) .settings( + crossScalaVersions := Seq("2.12.13"), + scalaVersion := crossScalaVersions.value.head, run / fork := true, // Needed if you run this project directly libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value @@ -73,10 +75,11 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - // we're still in 0.x land so we could choose to break bincompat, - // but let's at least be aware when we're doing it. also we should - // think about going 1.0, it's been a while - scalaModuleMimaPreviousVersion := Some("0.9.1"), + scalaModuleMimaPreviousVersion := { + // pending resolution of https://github.com/scalacenter/sbt-version-policy/issues/62 + if (isDotty.value) None + else Some("0.9.1") + }, mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._, ProblemFilters._ @@ -146,8 +149,14 @@ lazy val scalaJava8Compat = (project in file(".")) }, JavaDoc / javacOptions := Seq("-Xdoclint:none"), JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies += compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full), - Compile / scalacOptions += "-P:genjavadoc:out=" + (target.value / "java") + libraryDependencies ++= ( + if (isDotty.value) Seq() + else Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full)) + ), + Compile / scalacOptions ++= ( + if (isDotty.value) Seq() + else Seq(s"""-P:genjavadoc:out=${target.value / "java"}""") + ), ) } ) diff --git a/project/plugins.sbt b/project/plugins.sbt index 32698b2..e47c7d1 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,3 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0-RC5") +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.3") From a7fc68fb04ab0b247a13a9928bc712ec8aa03130 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Mar 2021 17:00:54 -0700 Subject: [PATCH 225/340] remove redundant code in build.sbt this is already handled by sbt-scala-module --- build.sbt | 3 --- 1 file changed, 3 deletions(-) diff --git a/build.sbt b/build.sbt index d081181..2978b49 100644 --- a/build.sbt +++ b/build.sbt @@ -22,8 +22,6 @@ ThisBuild / versionScheme := Some("early-semver") ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible lazy val commonSettings = Seq( - scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked"), - Compile / unmanagedSourceDirectories ++= { (Compile / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { @@ -33,7 +31,6 @@ lazy val commonSettings = Seq( } } }, - Test / unmanagedSourceDirectories ++= { (Test / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { From 0dbec1f9f57e26072c1ba5349b3c4129ee56363a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Mar 2021 17:17:22 -0700 Subject: [PATCH 226/340] avoid unchecked warning --- src/main/scala/scala/compat/java8/FutureConverters.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 794ae7e..7f75ee0 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -66,7 +66,7 @@ object FutureConverters { */ def toJava[T](f: Future[T]): CompletionStage[T] = { f match { - case p: P[T] => p.wrapped + case p: P[T @unchecked] => p.wrapped case _ => val cf = new CF[T](f) implicit val ec = InternalCallbackExecutor From 5160b411d4076697478e2f0aa1239ecd9994ce8e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 25 Mar 2021 17:17:42 -0700 Subject: [PATCH 227/340] for Scala 3, remove a type parameter from StreamConverters I do not fully understand why this was here, but Scala 3 was complaining: "Polymorphic refinement method valueStepper without matching type in parent trait MapOps is no longer allowed" simplifying the code as I have done in this commit compiles on both Scala versions and the tests still pass, and this is an obscure enough corner of the API that I'm not inclined to spend time really digging deeply into it (e.g. attempting to construct a test case that would now compile when it shouldn't, or vice versa) --- src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala index 47bfa05..309d4c3 100644 --- a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala @@ -86,7 +86,7 @@ trait StreamExtensions { implicit class MapHasParKeyValueStream[K, V, CC[X, Y] <: collection.MapOps[X, Y, collection.Map, _]](cc: CC[K, V]) { private type MapOpsWithEfficientKeyStepper = collection.MapOps[K, V, collection.Map, _] { def keyStepper[S <: Stepper[_]](implicit shape : StepperShape[K, S]) : S with EfficientSplit } - private type MapOpsWithEfficientValueStepper = collection.MapOps[K, V, collection.Map, _] { def valueStepper[V1 >: V, S <: Stepper[_]](implicit shape : StepperShape[V1, S]) : S with EfficientSplit } + private type MapOpsWithEfficientValueStepper = collection.MapOps[K, V, collection.Map, _] { def valueStepper[S <: Stepper[_]](implicit shape : StepperShape[V, S]) : S with EfficientSplit } private type MapOpsWithEfficientStepper = collection.MapOps[K, V, collection.Map, _] { def stepper[S <: Stepper[_]](implicit shape : StepperShape[(K, V), S]) : S with EfficientSplit } /** Create a parallel [[java.util.stream.Stream Java Stream]] for the keys of this map. If From 018682203d6ebb7eaa3b1f5605ada571dab820ad Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 29 Mar 2021 11:06:20 -0700 Subject: [PATCH 228/340] upgrade to sbt 1.5 (was 1.4) --- project/build.properties | 2 +- project/plugins.sbt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/project/build.properties b/project/build.properties index dbae93b..af4ff6f 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.9 +sbt.version=1.5.0-RC2 diff --git a/project/plugins.sbt b/project/plugins.sbt index e47c7d1..32698b2 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,2 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0-RC5") -addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.5.3") From 6950d8f0299c842b795a2dd70e9dcbdea8a99dbc Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 29 Mar 2021 11:06:12 -0700 Subject: [PATCH 229/340] add Scala 3.0.0-RC2 to crossbuild --- .travis.yml | 1 + build.sbt | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a3363c..62afe56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ import: scala/scala-dev:travis/default.yml language: scala scala: + - 3.0.0-RC2 - 3.0.0-RC1 - 2.11.12 - 2.12.13 diff --git a/build.sbt b/build.sbt index 2978b49..578e555 100644 --- a/build.sbt +++ b/build.sbt @@ -72,11 +72,11 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - scalaModuleMimaPreviousVersion := { + scalaModuleMimaPreviousVersion := (CrossVersion.partialVersion(scalaVersion.value) match { // pending resolution of https://github.com/scalacenter/sbt-version-policy/issues/62 - if (isDotty.value) None - else Some("0.9.1") - }, + case Some((3, _)) => None + case _ => Some("0.9.1") + }), mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._, ProblemFilters._ @@ -146,14 +146,14 @@ lazy val scalaJava8Compat = (project in file(".")) }, JavaDoc / javacOptions := Seq("-Xdoclint:none"), JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), - libraryDependencies ++= ( - if (isDotty.value) Seq() - else Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full)) - ), - Compile / scalacOptions ++= ( - if (isDotty.value) Seq() - else Seq(s"""-P:genjavadoc:out=${target.value / "java"}""") - ), + libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { + case Some((3, _)) => Seq() + case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full)) + }), + Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match { + case Some((3, _)) => Seq() + case _ => Seq(s"""-P:genjavadoc:out=${target.value / "java"}""") + }), ) } ) From e12877cef821dcdf968c842dff794ca098f1a828 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 29 Mar 2021 13:33:15 -0700 Subject: [PATCH 230/340] bump MiMa reference version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 578e555..1c17e31 100644 --- a/build.sbt +++ b/build.sbt @@ -75,7 +75,7 @@ lazy val scalaJava8Compat = (project in file(".")) scalaModuleMimaPreviousVersion := (CrossVersion.partialVersion(scalaVersion.value) match { // pending resolution of https://github.com/scalacenter/sbt-version-policy/issues/62 case Some((3, _)) => None - case _ => Some("0.9.1") + case _ => Some("1.0.0-RC1") }), mimaBinaryIssueFilters ++= { From be28cdb6901563646d82244e6c9e76e3abe5303f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 29 Mar 2021 14:16:45 -0700 Subject: [PATCH 231/340] give sbt more heap I found I needed it when using `+`, e.g. `+test` not really sure how much more is needed... shrug --- .jvmopts | 1 + 1 file changed, 1 insertion(+) create mode 100644 .jvmopts diff --git a/.jvmopts b/.jvmopts new file mode 100644 index 0000000..56aefe0 --- /dev/null +++ b/.jvmopts @@ -0,0 +1 @@ +-Xmx4G From b02dc3a19c13a475bb04c524a2510416d232b75c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 12 Apr 2021 05:35:44 +0200 Subject: [PATCH 232/340] Update sbt to 1.5.0 (#219) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index af4ff6f..e67343a 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.0-RC2 +sbt.version=1.5.0 From ba36c949c5f621bc8b3abea304e516f3f889252e Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 19 Apr 2021 11:20:30 -0700 Subject: [PATCH 233/340] add Scala 3.0.0-RC3 (and drop RC1) (#220) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 62afe56..7747585 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,8 @@ import: scala/scala-dev:travis/default.yml language: scala scala: + - 3.0.0-RC3 - 3.0.0-RC2 - - 3.0.0-RC1 - 2.11.12 - 2.12.13 - 2.13.5 From 13bf116f99ae08d67ce3abf6ea0fa8abd5d13669 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 19 Apr 2021 14:43:51 -0700 Subject: [PATCH 234/340] fix backpublishing (copy changes from scala-xml repo) (#222) --- build.sh | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/build.sh b/build.sh index 8dcf234..962adb9 100755 --- a/build.sh +++ b/build.sh @@ -10,11 +10,13 @@ set -e # sbt-dynver sets the version number from the tag # sbt-travisci sets the Scala version from the travis job matrix -# When a new binary incompatible Scala version becomes available, a previously released version -# can be released using that new Scala version by creating a new tag containing the Scala version -# after a hash, e.g., v1.2.3#2.13.0-M3. +# To back-publish an existing release for a new Scala / Scala.js / Scala Native version: +# - check out the tag for the version that needs to be published +# - change `.travis.yml` to adjust the version numbers and trim down the build matrix as necessary +# - commit the changes and tag this new revision with an arbitrary suffix after a hash, e.g., +# `v1.2.3#dotty-0.27` (the suffix is ignored, the version will be `1.2.3`) -# For normal tags that are cross-built, we release on JDK 8 for Scala 2.x +# We release on JDK 8 (for Scala 2.x and Dotty 0.x) isReleaseJob() { if [[ "$ADOPTOPENJDK" == "8" ]]; then true @@ -23,43 +25,26 @@ isReleaseJob() { fi } -# For tags that define a Scala version, we pick the jobs of one Scala version (2.13.x) to do the releases -isTagScalaReleaseJob() { - if [[ "$ADOPTOPENJDK" == "8" && "$TRAVIS_SCALA_VERSION" =~ ^2\.13\.[0-9]+$ ]]; then - true - else - false - fi -} +projectPrefix=scalaJava8Compat verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" -tagPat="^v$verPat(#$verPat)?$" +tagPat="^v$verPat(#.*)?$" if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then releaseTask="ci-release" - tagScalaVer=$(echo $TRAVIS_TAG | sed s/[^#]*// | sed s/^#//) - if [[ "$tagScalaVer" == "" ]]; then - if ! isReleaseJob; then - echo "Not releasing on Java $ADOPTOPENJDK with Scala $TRAVIS_SCALA_VERSION" - exit 0 - fi - else - if isTagScalaReleaseJob; then - setTagScalaVersion='set every scalaVersion := "'$tagScalaVer'"' - else - echo "The releases for Scala $tagScalaVer are built by other jobs in the travis job matrix" - exit 0 - fi + if ! isReleaseJob; then + echo "Not releasing on Java $ADOPTOPENJDK with Scala $TRAVIS_SCALA_VERSION" + exit 0 fi fi # default is +publishSigned; we cross-build with travis jobs, not sbt's crossScalaVersions -export CI_RELEASE="publishSigned" -export CI_SNAPSHOT_RELEASE="publish" +export CI_RELEASE="${projectPrefix}publishSigned" +export CI_SNAPSHOT_RELEASE="${projectPrefix}publish" # default is sonatypeBundleRelease, which closes and releases the staging repo # see https://github.com/xerial/sbt-sonatype#commands # for now, until we're confident in the new release scripts, just close the staging repo. export CI_SONATYPE_RELEASE="; sonatypePrepare; sonatypeBundleUpload; sonatypeClose" -sbt "$setTagScalaVersion" clean test versionPolicyCheck publishLocal $releaseTask +sbt clean ${projectPrefix}test ${projectPrefix}versionPolicyCheck ${projectPrefix}publishLocal $releaseTask From dbeb2a455280d14f151f945a85dff7837aa67882 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 19 Apr 2021 14:59:58 -0700 Subject: [PATCH 235/340] another publishing fix (#223) --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 962adb9..4b1f48a 100755 --- a/build.sh +++ b/build.sh @@ -25,7 +25,7 @@ isReleaseJob() { fi } -projectPrefix=scalaJava8Compat +projectPrefix=scalaJava8Compat/ verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" tagPat="^v$verPat(#.*)?$" From 3163f7c615d742bf95737e53d8bf226c676aa715 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 28 Apr 2021 16:20:06 +0200 Subject: [PATCH 236/340] Update sbt to 1.5.1 (#224) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e67343a..f0be67b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.0 +sbt.version=1.5.1 From 806ae6edd7c46c6067f9a31efe0452c483229c33 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 5 May 2021 23:04:30 +0200 Subject: [PATCH 237/340] Update sbt-scala-module to 2.3.0 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 32698b2..028d3ca 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.0") addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0-RC5") From d129747ac2679bfea0fc18a7f229af34a6a7d043 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 5 May 2021 14:46:53 -0700 Subject: [PATCH 238/340] add Automatic-Module-Name --- build.sbt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1c17e31..13d8357 100644 --- a/build.sbt +++ b/build.sbt @@ -57,7 +57,8 @@ lazy val scalaJava8Compat = (project in file(".")) .settings(ScalaModulePlugin.scalaModuleOsgiSettings) .settings(commonSettings) .settings( - name := "scala-java8-compat" + name := "scala-java8-compat", + scalaModuleAutomaticModuleName := Some("scala.compat.java8"), ) .settings( fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath From 04d377fb18b9a57af7fbed8ea575bc1ccdaf1d95 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 13 May 2021 20:13:48 +0200 Subject: [PATCH 239/340] Update sbt-version-policy to 1.0.0 (#227) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 32698b2..b89a6d5 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.4") -addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0-RC5") +addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0") From cfb747f8f9049fd0065d02ef162146ded69baece Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 13 May 2021 20:14:25 +0200 Subject: [PATCH 240/340] Update sbt to 1.5.2 (#226) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index f0be67b..19479ba 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.1 +sbt.version=1.5.2 From ee3b9783f19d1b68444d4340096869e04c37094a Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 13 May 2021 14:09:41 -0700 Subject: [PATCH 241/340] add Scala 3.0.0 to crossbuild (and drop -RC2) (#229) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7747585..ae91b71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,8 @@ import: scala/scala-dev:travis/default.yml language: scala scala: + - 3.0.0 - 3.0.0-RC3 - - 3.0.0-RC2 - 2.11.12 - 2.12.13 - 2.13.5 From 4858d4d42eeb7ac4e33df6012b7e5849f822de5b Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 14 May 2021 01:16:06 +0200 Subject: [PATCH 242/340] Update sbt-version-policy to 1.0.1 (#230) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 401e5de..69c1257 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.0") -addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.0") +addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.1") From 0b16b021109858b22d76df84270b29757e296c52 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 13 May 2021 16:47:45 -0700 Subject: [PATCH 243/340] update readme and build, post 1.0.0 --- README.md | 14 +++++++++++--- build.sbt | 6 +----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e21f48b..1a39420 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,20 @@ # scala-java8-compat [![Build Status](https://travis-ci.org/scala/scala-java8-compat.svg?branch=master)](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.13) -A Java 8 compatibility kit for Scala. - -The API is currently still experimental: we do not yet guarantee source or binary compatibility with future releases. +A Java 8 compatibility kit for Scala 2.12 and 2.11. Javadoc is [here](https://javadoc.io/doc/org.scala-lang.modules/scala-java8-compat_2.13/latest/index.html). +## Do you need this? + +If you are using Scala 2.13 or newer only, then don't use this library! Use the classes under `scala.jdk` instead; they were added to the standard library in 2.13. + +We do publish 2.13 and 3.0 artifacts of scala-java8-compat, but they're only intended to be used in projects which crossbuild with 2.12 and/or 2.11. + +## Maintenance status + +This library is community-maintained. (The Scala team at Lightbend provides infrastructure and oversight.) + ## Functional Interfaces for Scala functions A set of [Functional Interfaces](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) diff --git a/build.sbt b/build.sbt index 13d8357..2c2e5f2 100644 --- a/build.sbt +++ b/build.sbt @@ -73,11 +73,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - scalaModuleMimaPreviousVersion := (CrossVersion.partialVersion(scalaVersion.value) match { - // pending resolution of https://github.com/scalacenter/sbt-version-policy/issues/62 - case Some((3, _)) => None - case _ => Some("1.0.0-RC1") - }), + scalaModuleMimaPreviousVersion := Some("1.0.0"), mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._, ProblemFilters._ From 440f2a92ef3bb6b2c3b28a8c028169b2d18ddd44 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 28 May 2021 14:34:24 +0200 Subject: [PATCH 244/340] Update scala-library to 2.12.14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 13d8357..cf322fe 100644 --- a/build.sbt +++ b/build.sbt @@ -45,7 +45,7 @@ lazy val commonSettings = Seq( lazy val fnGen = (project in file("fnGen")) .settings(commonSettings) .settings( - crossScalaVersions := Seq("2.12.13"), + crossScalaVersions := Seq("2.12.14"), scalaVersion := crossScalaVersions.value.head, run / fork := true, // Needed if you run this project directly libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, From b4e1a12934e77d059c58b7213c1ff7fd36963050 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 1 Jun 2021 09:08:10 +0200 Subject: [PATCH 245/340] Update sbt to 1.5.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 19479ba..67d27a1 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.2 +sbt.version=1.5.3 From 219302edee7740e6c4b100d732a0d465f8682888 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Wed, 9 Jun 2021 10:18:54 +0900 Subject: [PATCH 246/340] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ae91b71..42f51eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ scala: - 3.0.0 - 3.0.0-RC3 - 2.11.12 - - 2.12.13 + - 2.12.14 - 2.13.5 env: From 188d402a8f79bb82677e89e6b485e93a9883e07c Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 26 May 2021 17:52:28 +0200 Subject: [PATCH 247/340] Update sbt-scala-module to 2.3.1 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 69c1257..06a9a80 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.1") addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.1") From b6cf6864d6a7197fc379988d87d7a07a34b543a7 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 14 Jun 2021 09:01:53 +0200 Subject: [PATCH 248/340] Update sbt to 1.5.4 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 67d27a1..9edb75b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.3 +sbt.version=1.5.4 From b6e9df8c15f6b4c71d77173272d2ee6851760c50 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Sat, 19 Jun 2021 21:11:09 -0700 Subject: [PATCH 249/340] upgrade genjavadoc to version available for Scala 2.12.14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index cf322fe..ced0231 100644 --- a/build.sbt +++ b/build.sbt @@ -149,7 +149,7 @@ lazy val scalaJava8Compat = (project in file(".")) JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() - case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.16" cross CrossVersion.full)) + case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.17" cross CrossVersion.full)) }), Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() From fa3286ca2e3238d1134e03eab40a1d24eb924e41 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 12 Jul 2021 13:38:07 +0200 Subject: [PATCH 250/340] Update sbt to 1.5.5 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 9edb75b..10fd9ee 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.4 +sbt.version=1.5.5 From 57e1f7ccaa67dcac2b4227ab1a6ee0fcb5f42023 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 30 Jul 2021 01:49:23 +0200 Subject: [PATCH 251/340] Update sbt-version-policy to 1.2.1 (#240) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 06a9a80..486c4b9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.1") -addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.0.1") +addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.2.1") From 2eb5b3e330ead654a16d796336f22201478f89cf Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 3 Aug 2021 23:23:28 +0200 Subject: [PATCH 252/340] Update sbt-scala-module to 2.4.0 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 486c4b9..926f886 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1,2 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.3.1") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.4.0") addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.2.1") From f0192a6b7b32e9aab11b2649eef581beb3d01c0b Mon Sep 17 00:00:00 2001 From: Julien Richard-Foy Date: Tue, 17 Aug 2021 09:40:01 +0200 Subject: [PATCH 253/340] Remove explicit dependency to sbt-version-policy and update build definition --- build.sbt | 6 +----- build.sh | 3 ++- project/plugins.sbt | 1 - 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/build.sbt b/build.sbt index 5ae4b8c..d3639ec 100644 --- a/build.sbt +++ b/build.sbt @@ -18,10 +18,8 @@ def osgiExport(scalaVersion: String, version: String) = { }) ++ Seq(s"scala.compat.java8.*;version=${version}") } -ThisBuild / versionScheme := Some("early-semver") -ThisBuild / versionPolicyIntention := Compatibility.BinaryAndSourceCompatible - lazy val commonSettings = Seq( + versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { (Compile / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { @@ -73,8 +71,6 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - scalaModuleMimaPreviousVersion := Some("1.0.0"), - mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._, ProblemFilters._ Seq( diff --git a/build.sh b/build.sh index 4b1f48a..1d72bea 100755 --- a/build.sh +++ b/build.sh @@ -31,6 +31,7 @@ verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" tagPat="^v$verPat(#.*)?$" if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then + versionCheckTask="versionCheck" releaseTask="ci-release" if ! isReleaseJob; then echo "Not releasing on Java $ADOPTOPENJDK with Scala $TRAVIS_SCALA_VERSION" @@ -47,4 +48,4 @@ export CI_SNAPSHOT_RELEASE="${projectPrefix}publish" # for now, until we're confident in the new release scripts, just close the staging repo. export CI_SONATYPE_RELEASE="; sonatypePrepare; sonatypeBundleUpload; sonatypeClose" -sbt clean ${projectPrefix}test ${projectPrefix}versionPolicyCheck ${projectPrefix}publishLocal $releaseTask +sbt clean ${projectPrefix}test ${projectPrefix}publishLocal $versionCheckTask $releaseTask diff --git a/project/plugins.sbt b/project/plugins.sbt index 926f886..0401cc3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,2 +1 @@ addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.4.0") -addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "1.2.1") From ae1e23ae92142c8caca2fb5563d2a6213d55b462 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 15 Sep 2021 02:20:07 +0200 Subject: [PATCH 254/340] Update scala-library to 2.12.15 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d3639ec..0b34569 100644 --- a/build.sbt +++ b/build.sbt @@ -43,7 +43,7 @@ lazy val commonSettings = Seq( lazy val fnGen = (project in file("fnGen")) .settings(commonSettings) .settings( - crossScalaVersions := Seq("2.12.14"), + crossScalaVersions := Seq("2.12.15"), scalaVersion := crossScalaVersions.value.head, run / fork := true, // Needed if you run this project directly libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, From dcc5f14af570feffa858ba454919c90ba013fcb0 Mon Sep 17 00:00:00 2001 From: kenji yoshida <6b656e6a69@gmail.com> Date: Tue, 28 Sep 2021 11:43:07 +0900 Subject: [PATCH 255/340] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 42f51eb..78948a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ scala: - 3.0.0 - 3.0.0-RC3 - 2.11.12 - - 2.12.14 + - 2.12.15 - 2.13.5 env: From 89c655de4f39ba15fc95c966c9e128ea3a74a437 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 28 Sep 2021 17:34:32 -0600 Subject: [PATCH 256/340] in with GitHub Actions, out with Travis-CI --- .github/workflows/ci.yml | 25 +++++++++ .github/workflows/release.yml | 21 ++++++++ .travis.yml | 25 --------- README.md | 3 +- benchmark/build.sbt | 4 +- build.sbt | 8 ++- build.sh | 51 ------------------- project/plugins.sbt | 2 +- .../compat/java8/collectionImpl/package.scala | 12 +++++ .../converterImpl/StepperExtensions.scala | 12 +++++ .../java8/FuturesConvertersImplCompat.scala | 12 +++++ .../java8/FuturesConvertersImplCompat.scala | 12 +++++ .../java8/runtime/LambdaDeserializerTest.java | 13 +++++ 13 files changed, 118 insertions(+), 82 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml delete mode 100644 .travis.yml delete mode 100755 build.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..98ac851 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: test +on: + push: + branches: + - main + pull_request: +jobs: + test: + strategy: + fail-fast: false + matrix: + java: [8, 11, 17] + scala: [2.11.12, 2.12.15, 2.13.6, 3.0.2] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: coursier/cache-action@v6 + - uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: ${{matrix.java}} + - name: Test + run: sbt ++${{matrix.scala}} test headerCheck versionPolicyCheck package diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..dc33711 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,21 @@ +name: Release +on: + push: + tags: ["*"] +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: 8 + - run: sbt versionCheck ci-release + env: + PGP_PASSPHRASE: ${{secrets.PGP_PASSPHRASE}} + PGP_SECRET: ${{secrets.PGP_SECRET}} + SONATYPE_PASSWORD: ${{secrets.SONATYPE_PASSWORD}} + SONATYPE_USERNAME: ${{secrets.SONATYPE_USERNAME}} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 78948a7..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: ~> 1.0 # needed for imports - -import: scala/scala-dev:travis/default.yml - -language: scala - -scala: - - 3.0.0 - - 3.0.0-RC3 - - 2.11.12 - - 2.12.15 - - 2.13.5 - -env: - - ADOPTOPENJDK=8 - - ADOPTOPENJDK=11 - -install: - - git fetch --tags # get all tags for sbt-dynver - -script: ./build.sh - -notifications: - email: - - seth.tisue@lightbend.com diff --git a/README.md b/README.md index 1a39420..34f30b9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -# scala-java8-compat [![Build Status](https://travis-ci.org/scala/scala-java8-compat.svg?branch=master)](https://travis-ci.org/scala/scala-java8-compat) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.13) - +# scala-java8-compat [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.11) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.12) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_2.13) [](http://search.maven.org/#search%7Cga%7C1%7Cg%3Aorg.scala-lang.modules%20a%3Ascala-java8-compat_3) A Java 8 compatibility kit for Scala 2.12 and 2.11. diff --git a/benchmark/build.sbt b/benchmark/build.sbt index 0703b42..393b763 100644 --- a/benchmark/build.sbt +++ b/benchmark/build.sbt @@ -5,8 +5,8 @@ val parseJmh = TaskKey[Unit]("parseJmh", "Parses JMH benchmark logs in results/j lazy val root = (project in file(".")).settings( name := "java8-compat-bench", - scalaVersion := "2.11.11", - crossScalaVersions := List("2.11.11" /* TODO, "2.12.0-M4"*/), + scalaVersion := "2.11.12", + crossScalaVersions := List("2.11.12" /* TODO, "2.12.0-M4"*/), organization := "org.scala-lang.modules", version := "0.6.0-SNAPSHOT", unmanagedJars in Compile ++= Seq(baseDirectory.value / "../target/scala-2.11/scala-java8-compat_2.11-0.9.0-SNAPSHOT.jar"), diff --git a/build.sbt b/build.sbt index 0b34569..fdbe60d 100644 --- a/build.sbt +++ b/build.sbt @@ -18,7 +18,13 @@ def osgiExport(scalaVersion: String, version: String) = { }) ++ Seq(s"scala.compat.java8.*;version=${version}") } +// shouldn't be necessary anymore after https://github.com/lampepfl/dotty/pull/13498 +// makes it into a release +ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" + lazy val commonSettings = Seq( + crossScalaVersions := Seq("2.13.6", "2.12.15", "2.11.12", "3.0.2"), + scalaVersion := crossScalaVersions.value.head, versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { (Compile / unmanagedSourceDirectories).value.flatMap { dir => @@ -141,7 +147,7 @@ lazy val scalaJava8Compat = (project in file(".")) JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() - case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.17" cross CrossVersion.full)) + case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.18" cross CrossVersion.full)) }), Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() diff --git a/build.sh b/build.sh deleted file mode 100755 index 1d72bea..0000000 --- a/build.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -set -e - -# Builds of tagged revisions are published to sonatype staging. - -# Travis runs a build on new revisions and on new tags, so a tagged revision is built twice. -# Builds for a tag have TRAVIS_TAG defined, which we use for identifying tagged builds. - -# sbt-dynver sets the version number from the tag -# sbt-travisci sets the Scala version from the travis job matrix - -# To back-publish an existing release for a new Scala / Scala.js / Scala Native version: -# - check out the tag for the version that needs to be published -# - change `.travis.yml` to adjust the version numbers and trim down the build matrix as necessary -# - commit the changes and tag this new revision with an arbitrary suffix after a hash, e.g., -# `v1.2.3#dotty-0.27` (the suffix is ignored, the version will be `1.2.3`) - -# We release on JDK 8 (for Scala 2.x and Dotty 0.x) -isReleaseJob() { - if [[ "$ADOPTOPENJDK" == "8" ]]; then - true - else - false - fi -} - -projectPrefix=scalaJava8Compat/ - -verPat="[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9-]+)?" -tagPat="^v$verPat(#.*)?$" - -if [[ "$TRAVIS_TAG" =~ $tagPat ]]; then - versionCheckTask="versionCheck" - releaseTask="ci-release" - if ! isReleaseJob; then - echo "Not releasing on Java $ADOPTOPENJDK with Scala $TRAVIS_SCALA_VERSION" - exit 0 - fi -fi - -# default is +publishSigned; we cross-build with travis jobs, not sbt's crossScalaVersions -export CI_RELEASE="${projectPrefix}publishSigned" -export CI_SNAPSHOT_RELEASE="${projectPrefix}publish" - -# default is sonatypeBundleRelease, which closes and releases the staging repo -# see https://github.com/xerial/sbt-sonatype#commands -# for now, until we're confident in the new release scripts, just close the staging repo. -export CI_SONATYPE_RELEASE="; sonatypePrepare; sonatypeBundleUpload; sonatypeClose" - -sbt clean ${projectPrefix}test ${projectPrefix}publishLocal $versionCheckTask $releaseTask diff --git a/project/plugins.sbt b/project/plugins.sbt index 0401cc3..a668f72 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.4.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.0.0") diff --git a/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala index ab5cfca..c02ebce 100644 --- a/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala +++ b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8 package object collectionImpl { diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala index 15f384a..dd75253 100644 --- a/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.compat.java8.converterImpl import scala.collection.convert.StreamExtensions.AccumulatorFactoryInfo diff --git a/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala index ea4cf4d..754f784 100644 --- a/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala +++ b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.concurrent.java8 import scala.concurrent.ExecutionContext diff --git a/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala index 4262f7a..cca7feb 100644 --- a/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala +++ b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -1,3 +1,15 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + package scala.concurrent.java8 import scala.concurrent.Future diff --git a/src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java b/src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java index 6640a44..a6b71d2 100644 --- a/src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java +++ b/src/test/java-2.11/scala/compat/java8/runtime/LambdaDeserializerTest.java @@ -13,6 +13,7 @@ package scala.compat.java8.runtime; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import java.io.Serializable; @@ -26,26 +27,33 @@ public final class LambdaDeserializerTest { private LambdaHost lambdaHost = new LambdaHost(); + // We skip most tests on Java 17+ because of https://github.com/scala/bug/issues/12419 + // which we only fixed for 2.12+ + @Test public void serializationPrivate() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F1 f1 = lambdaHost.lambdaBackedByPrivateImplMethod(); Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); } @Test public void serializationStatic() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); } @Test public void serializationVirtualMethodReference() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F1 f1 = lambdaHost.lambdaBackedByVirtualMethodReference(); Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); } @Test public void serializationInterfaceMethodReference() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F1 f1 = lambdaHost.lambdaBackedByInterfaceMethodReference(); I i = new I() { }; @@ -54,18 +62,21 @@ public void serializationInterfaceMethodReference() { @Test public void serializationStaticMethodReference() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F1 f1 = lambdaHost.lambdaBackedByStaticMethodReference(); Assert.assertEquals(f1.apply(true), reconstitute(f1).apply(true)); } @Test public void serializationNewInvokeSpecial() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); Assert.assertEquals(f1.apply(), reconstitute(f1).apply()); } @Test public void uncached() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); F0 reconstituted1 = reconstitute(f1); F0 reconstituted2 = reconstitute(f1); @@ -74,6 +85,7 @@ public void uncached() { @Test public void cached() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); HashMap cache = new HashMap<>(); F0 f1 = lambdaHost.lambdaBackedByConstructorCall(); F0 reconstituted1 = reconstitute(f1, cache); @@ -83,6 +95,7 @@ public void cached() { @Test public void cachedStatic() { + Assume.assumeFalse(scala.util.Properties.isJavaAtLeast("17")); HashMap cache = new HashMap<>(); F1 f1 = lambdaHost.lambdaBackedByStaticImplMethod(); // Check that deserialization of a static lambda always returns the From 20ddb40b210d727c8d28d8cfb7c084a3fac6beff Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 28 Sep 2021 18:49:02 -0600 Subject: [PATCH 257/340] don't attempt to run genjavadoc on Scala 3 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index fdbe60d..7c82719 100644 --- a/build.sbt +++ b/build.sbt @@ -130,7 +130,7 @@ lazy val scalaJava8Compat = (project in file(".")) sys.error("Java 8 or higher is required for this project.") }, - packageDoc / publishArtifact := !disableDocs + packageDoc / publishArtifact := !disableDocs && !scalaVersion.value.startsWith("3.") ) .settings( inConfig(JavaDoc)(Defaults.configSettings) ++ { From fb0c4de088778d2ee42597a8e7507111420dfa5f Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 4 Oct 2021 16:31:42 -0600 Subject: [PATCH 258/340] AdoptOpenJDK is now Temurin (#249) --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98ac851..932ecdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: coursier/cache-action@v6 - uses: actions/setup-java@v2 with: - distribution: adopt + distribution: temurin java-version: ${{matrix.java}} - name: Test run: sbt ++${{matrix.scala}} test headerCheck versionPolicyCheck package diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc33711..d69ab72 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-java@v2 with: - distribution: adopt + distribution: temurin java-version: 8 - run: sbt versionCheck ci-release env: From 525679cc989102510ccf4fcfe577a17207edcf59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bu=CC=80i=20Vie=CC=A3=CC=82t=20Tha=CC=80nh?= Date: Fri, 1 Jan 2021 09:05:15 +0700 Subject: [PATCH 259/340] Reimplement WrapFnGen without scala-compiler & scala-reflect dependencies Fix #247 --- build.sbt | 13 +-- project/WrapFnGen.scala | 236 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 10 deletions(-) create mode 100644 project/WrapFnGen.scala diff --git a/build.sbt b/build.sbt index 7c82719..c466f06 100644 --- a/build.sbt +++ b/build.sbt @@ -65,8 +65,6 @@ lazy val scalaJava8Compat = (project in file(".")) scalaModuleAutomaticModuleName := Some("scala.compat.java8"), ) .settings( - fork := true, // This must be set so that runner task is forked when it runs fnGen and the compiler gets a proper classpath - OsgiKeys.exportPackage := osgiExport(scalaVersion.value, version.value), OsgiKeys.privatePackage := List("scala.concurrent.java8.*"), @@ -93,14 +91,9 @@ lazy val scalaJava8Compat = (project in file(".")) testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), (Compile / sourceGenerators) += Def.task { - val out = (Compile / sourceManaged).value - if (!out.exists) IO.createDirectory(out) - val canon = out.getCanonicalPath - val args = (new File(canon, "FunctionConverters.scala")).toString :: Nil - val runTarget = (fnGen / Compile / mainClass).value getOrElse "No main class defined for function conversion generator" - val classPath = (fnGen / Compile / fullClasspath).value - runner.value.run(runTarget, classPath.files, args, streams.value.log) - (out ** "*.scala").get + val f = (Compile / sourceManaged).value / "FunctionConverters.scala" + IO.write(f, WrapFnGen.code) + Seq(f) }.taskValue, Compile / sourceGenerators += Def.task { diff --git a/project/WrapFnGen.scala b/project/WrapFnGen.scala new file mode 100644 index 0000000..eaf4482 --- /dev/null +++ b/project/WrapFnGen.scala @@ -0,0 +1,236 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +import scala.collection.mutable + +object WrapFnGen { + /** all 43 interfaces in java.util.function package */ + private lazy val allJfn = Seq( + "BiConsumer[T, U]: accept(T, U): Unit", + "BiFunction[T, U, R]: apply(T, U): R", + "BiPredicate[T, U]: test(T, U): Boolean", + "BinaryOperator[T]: apply(T, T): T", + "BooleanSupplier: getAsBoolean: Boolean", + "Consumer[T]: accept(T): Unit", + "DoubleBinaryOperator: applyAsDouble(Double, Double): Double", + "DoubleConsumer: accept(Double): Unit", + "DoubleFunction[R]: apply(Double): R", + "DoublePredicate: test(Double): Boolean", + "DoubleSupplier: getAsDouble: Double", + "DoubleToIntFunction: applyAsInt(Double): Int", + "DoubleToLongFunction: applyAsLong(Double): Long", + "DoubleUnaryOperator: applyAsDouble(Double): Double", + "Function[T, R]: apply(T): R", + "IntBinaryOperator: applyAsInt(Int, Int): Int", + "IntConsumer: accept(Int): Unit", + "IntFunction[R]: apply(Int): R", + "IntPredicate: test(Int): Boolean", + "IntSupplier: getAsInt: Int", + "IntToDoubleFunction: applyAsDouble(Int): Double", + "IntToLongFunction: applyAsLong(Int): Long", + "IntUnaryOperator: applyAsInt(Int): Int", + "LongBinaryOperator: applyAsLong(Long, Long): Long", + "LongConsumer: accept(Long): Unit", + "LongFunction[R]: apply(Long): R", + "LongPredicate: test(Long): Boolean", + "LongSupplier: getAsLong: Long", + "LongToDoubleFunction: applyAsDouble(Long): Double", + "LongToIntFunction: applyAsInt(Long): Int", + "LongUnaryOperator: applyAsLong(Long): Long", + "ObjDoubleConsumer[T]: accept(T, Double): Unit", + "ObjIntConsumer[T]: accept(T, Int): Unit", + "ObjLongConsumer[T]: accept(T, Long): Unit", + "Predicate[T]: test(T): Boolean", + "Supplier[T]: get: T", + "ToDoubleBiFunction[T, U]: applyAsDouble(T, U): Double", + "ToDoubleFunction[T]: applyAsDouble(T): Double", + "ToIntBiFunction[T, U]: applyAsInt(T, U): Int", + "ToIntFunction[T]: applyAsInt(T): Int", + "ToLongBiFunction[T, U]: applyAsLong(T, U): Long", + "ToLongFunction[T]: applyAsLong(T): Long", + "UnaryOperator[T]: apply(T): T", + ).map(Jfn.apply) + + /** @param sig - ex: "BiConsumer[T,U]: accept(T,U): Unit" + * or "DoubleToIntFunction: applyAsInt(Double): Int" */ + case class Jfn(sig: String) { + val Array( + iface, // interface name included type args, ex: BiConsumer[T,U] | DoubleToIntFunction + _method, // Temp val, ex: accept(T,U) | applyAsInt(Double) + rType // java function return type, ex: Unit | Int + ) = sig.split(':').map(_.trim) + + // interface name and java interface's type args, + // ex: ("BiConsumer", "[T,U]") | ("DoubleToIntFunction", "") + val (ifaceName, jtargs) = iface.span(_ != '[') + + // java method name and temp val, ex: "accept" -> "(T,U)" | "applyAsInt" -> "(Double)" + val (jmethod, _targs) = _method.span(_ != '(') + + // java method's type args, ex: Seq("T", "U") | Seq("Double") + val pTypes: Seq[String] = _targs.unwrapMe + + // arguments names, ex: Seq("x1", "x2") + val args: Seq[String] = pTypes.indices.map { i => "x" + (i+1) } + // ex: "(x1: T, x2: U)" | "(x1: Double)" + val argsDecl: String = args.zip(pTypes).map { + // Don't really need this case. Only here so the generated code is + // exactly == the code gen by the old method using scala-compiler + scala-reflect + case (p, t @ ("Double"|"Long"|"Int")) => s"$p: scala.$t" + case (p, t) => s"$p: $t" + }.mkString("(", ", ", ")") + // ex: "(x1, x2)" + val argsCall: String = args.mkString("(", ", ", ")") + + // arity of scala.Function + val arity: Int = args.length + + // ex: "java.util.function.BiConsumer[T,U]" | "java.util.function.DoubleToIntFunction" + val javaFn = s"java.util.function.$iface" + + // ex: "scala.Function2[T, U, Unit]" | "scala.Function1[Double, Int]" + val scalaFn = s"scala.Function$arity[${(pTypes :+ rType).mkString(", ")}]" + + def fromJavaCls: String = + s"""class FromJava$iface(jf: $javaFn) extends $scalaFn { + | def apply$argsDecl = jf.$jmethod$argsCall + |}""".stripMargin + + val richAsFnClsName = s"Rich${ifaceName}AsFunction$arity$jtargs" + def richAsFnCls: String = + s"""class $richAsFnClsName(private val underlying: $javaFn) extends AnyVal { + | @inline def asScala: $scalaFn = new FromJava$iface(underlying) + |}""".stripMargin + + def asJavaCls: String = + s"""class AsJava$iface(sf: $scalaFn) extends $javaFn { + | def $jmethod$argsDecl = sf.apply$argsCall + |}""".stripMargin + + val richFnAsClsName = s"RichFunction${arity}As$iface" + def richFnAsCls: String = + s"""class $richFnAsClsName(private val underlying: $scalaFn) extends AnyVal { + | @inline def asJava: $javaFn = new AsJava$iface(underlying) + |}""".stripMargin + + def converterImpls: String = + s"""$fromJavaCls\n + |$richAsFnCls\n + |$asJavaCls\n + |$richFnAsCls\n + |""".stripMargin + + /** @return "implicit def enrichAsJavaXX.." code */ + def enrichAsJavaDef: String = { + // This is especially tricky because functions are contravariant in their arguments + // Need to prevent e.g. Any => String from "downcasting" itself to Int => String; we want the more exact conversion + // Instead of foo[A](f: (Int, A) => Long): Fuu[A] = new Foo[A](f) + // we want foo[X, A](f: (X, A) => Long)(implicit evX: Int =:= X): Fuu[A] = new Foo[A](f.asInstanceOf[(Int, A) => Long]) + // Instead of bar[A](f: A => A): Brr[A] = new Foo[A](f) + // we want bar[A, B](f: A => B)(implicit evB: A =:= B): Brr[A] = new Foo[A](f.asInstanceOf[A => B]) + + val finalTypes = Set("Double", "Long", "Int", "Boolean", "Unit") + val An = "A(\\d+)".r + val numberedA = mutable.Set.empty[Int] + val evidences = mutable.ArrayBuffer.empty[(String, String)] // ex: "A0" -> "Double" + numberedA ++= pTypes.collect{ case An(digits) if (digits.length < 10) => digits.toInt } + val scalafnTnames = (pTypes :+ rType).zipWithIndex.map { + case (pt, i) if i < pTypes.length && finalTypes(pt) || !finalTypes(pt) && pTypes.take(i).contains(pt) => + val j = Iterator.from(i).dropWhile(numberedA).next() + val genericName = s"A$j" + numberedA += j + evidences += (genericName -> pt) + genericName + case (pt, _) => pt + } + val scalafnTdefs = scalafnTnames.dropRight(if (finalTypes(rType)) 1 else 0).wrapMe() + val scalaFnGeneric = s"scala.Function${scalafnTnames.length - 1}[${scalafnTnames.mkString(", ")}]" + val evs = evidences + .map { case (generic, specific) => s"ev$generic: =:=[$generic, $specific]" } + .wrapMe("(implicit ", ")") + val sf = if (evs.isEmpty) "sf" else s"sf.asInstanceOf[$scalaFn]" + s"@inline implicit def enrichAsJava$ifaceName$scalafnTdefs(sf: $scalaFnGeneric)$evs: $richFnAsClsName = new $richFnAsClsName($sf)" + } + + def asScalaFromDef = s"@inline def asScalaFrom$iface(jf: $javaFn): $scalaFn = new FromJava$iface(jf)" + + def asJavaDef = s"@inline def asJava$iface(sf: $scalaFn): $javaFn = new AsJava$iface(sf)" + + def enrichAsScalaDef = s"@inline implicit def enrichAsScalaFrom$iface(jf: $javaFn): $richAsFnClsName = new $richAsFnClsName(jf)" + } + + def converters: String = { + val groups = allJfn + .map(jfn => jfn.jtargs.unwrapMe.length -> jfn.enrichAsJavaDef) + .groupBy(_._1) + .toSeq + .sortBy(_._1) + .reverse + val maxPriority = groups.head._1 + groups.map { case (priority, seq) => + val parent = + if (priority == maxPriority) "" + else s" extends Priority${priority + 1}FunctionConverters" + val me = + if (priority == 0) "package object FunctionConverters" + else s"trait Priority${priority}FunctionConverters" + + val enrichAsJava = seq.map(_._2) + val (asXx, enrichAsScala) = + if (priority != 0) Nil -> Nil + else allJfn.map { jfn => jfn.asScalaFromDef + "\n\n" + jfn.asJavaDef } -> + allJfn.map(_.enrichAsScalaDef) + + s"""$me$parent { + | import functionConverterImpls._ + |${asXx.mkString("\n\n\n").indentMe} + |${enrichAsJava.mkString("\n\n").indentMe} + |${enrichAsScala.mkString("\n\n").indentMe} + |}""".stripMargin + }.mkString("\n\n\n") + } + + def code: String = + s""" + |/* + | * Copyright EPFL and Lightbend, Inc. + | * This file auto-generated by WrapFnGen.scala. Do not modify directly. + | */ + | + |package scala.compat.java8 + | + |import language.implicitConversions + | + |package functionConverterImpls { + |${allJfn.map(_.converterImpls).mkString("\n").indentMe} + |} + |\n + |$converters + |""".stripMargin + + implicit class StringExt(private val s: String) extends AnyVal { + def indentMe: String = s.linesIterator.map(" " + _).mkString("\n") + def unwrapMe: Seq[String] = s match { + case "" => Nil + case _ => s + .substring(1, s.length - 1) // drop "(" and ")" or "[" and "]" + .split(',').map(_.trim).toSeq + } + } + + implicit class WrapMe(private val s: Seq[String]) extends AnyVal { + def wrapMe(start: String = "[", end: String = "]"): String = s match { + case Nil => "" + case _ => s.mkString(start, ", ", end) + } + } +} From 547d7d69aae0e77307dab4bd9d923ff8e92b8144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bu=CC=80i=20Vie=CC=A3=CC=82t=20Tha=CC=80nh?= Date: Fri, 1 Jan 2021 09:14:28 +0700 Subject: [PATCH 260/340] Remove `fnGen` sbt project --- build.sbt | 10 -- fnGen/WrapFnGen.scala | 314 ------------------------------------------ 2 files changed, 324 deletions(-) delete mode 100644 fnGen/WrapFnGen.scala diff --git a/build.sbt b/build.sbt index c466f06..fbca7af 100644 --- a/build.sbt +++ b/build.sbt @@ -46,16 +46,6 @@ lazy val commonSettings = Seq( }, ) -lazy val fnGen = (project in file("fnGen")) - .settings(commonSettings) - .settings( - crossScalaVersions := Seq("2.12.15"), - scalaVersion := crossScalaVersions.value.head, - run / fork := true, // Needed if you run this project directly - libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, - libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value - ) - lazy val scalaJava8Compat = (project in file(".")) .settings(ScalaModulePlugin.scalaModuleSettings) .settings(ScalaModulePlugin.scalaModuleOsgiSettings) diff --git a/fnGen/WrapFnGen.scala b/fnGen/WrapFnGen.scala deleted file mode 100644 index 794c104..0000000 --- a/fnGen/WrapFnGen.scala +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Scala (https://www.scala-lang.org) - * - * Copyright EPFL and Lightbend, Inc. - * - * Licensed under Apache License 2.0 - * (http://www.apache.org/licenses/LICENSE-2.0). - * - * See the NOTICE file distributed with this work for - * additional information regarding copyright ownership. - */ - -object WrapFnGen { - val copyright = - s""" - |/* - | * Copyright EPFL and Lightbend, Inc. - | * This file auto-generated by WrapFnGen.scala. Do not modify directly. - | */ - |""".stripMargin - - val packaging = "package scala.compat.java8" - - import scala.tools.nsc._ - val settings = new Settings(msg => sys.error(msg)) - settings.usejavacp.value = true - val compiler = new Global(settings) - val run = new compiler.Run - - import compiler._, definitions._ - - - implicit class IndentMe(v: Vector[String]) { - def indent: Vector[String] = v.map(" " + _) - } - - implicit class FlattenMe(v: Vector[Vector[String]]) { - def mkVec(join: String = ""): Vector[String] = { - val vb = Vector.newBuilder[String] - var first = true - v.foreach{ vi => - if (!first) vb += join - first = false - vb ++= vi - } - vb.result() - } - } - - implicit class DoubleFlattenMe(v: Vector[Vector[Vector[String]]]) { - def mkVecVec(join: String = ""): Vector[String] = { - val vb = Vector.newBuilder[String] - var first = true - v.foreach{ vi => - if (!first) { vb += join; vb += join } - first = false - var ifirst = true - vi.foreach{ vj => - if (!ifirst) vb += join - ifirst = false - vb ++= vj - } - } - vb.result() - } - } - - implicit class SplitMyLinesAndStuff(s: String) { - def toVec = s.linesIterator.toVector - def nonBlank = s.trim.length > 0 - } - - implicit class TreeToText(t: Tree) { - def text = showCode(t).replace("$", "").linesIterator.toVector - } - - case class Prioritized(lines: Vector[String], priority: Int) { - def withPriority(i: Int) = copy(priority = i) - } - - case class SamConversionCode( - base: String, - wrappedAsScala: Vector[String], - asScalaAnyVal: Vector[String], - implicitToScala: Vector[String], - asScalaDef: Vector[String], - wrappedAsJava: Vector[String], - asJavaAnyVal: Vector[String], - implicitToJava: Prioritized, - asJavaDef: Vector[String] - ) { - def impls: Vector[Vector[String]] = Vector(wrappedAsScala, asScalaAnyVal, wrappedAsJava, asJavaAnyVal) - def defs: Vector[Vector[String]] = Vector(asScalaDef, asJavaDef) - def withPriority(i: Int): SamConversionCode = copy(implicitToJava = implicitToJava.withPriority(i)) - } - object SamConversionCode { - def apply(scc: SamConversionCode*): (Vector[String], Vector[Vector[String]]) = { - val sccDepthSet = scc.map(_.implicitToJava.priority).toSet - val codes = - { - if (sccDepthSet != (0 to sccDepthSet.max).toSet) { - val sccDepthMap = sccDepthSet.toList.sorted.zipWithIndex.toMap - scc.map(x => x.withPriority(sccDepthMap(x.implicitToJava.priority))) - } - else scc - }.toVector.sortBy(_.base) - def priorityName(n: Int, pure: Boolean = false): String = { - val pre = - if (n <= 0) - if (pure) "FunctionConverters" - else s"package object ${priorityName(n, pure = true)}" - else - if (pure) s"Priority${n}FunctionConverters" - else s"trait ${priorityName(n, pure = true)}" - if (!pure && n < (sccDepthSet.size-1)) s"$pre extends ${priorityName(n+1, pure = true)}" else pre - } - val impls = - "package functionConverterImpls {" +: { - codes.map(_.impls).mkVecVec().indent - } :+ "}" - val traits = codes.filter(_.implicitToJava.priority > 0).groupBy(_.implicitToJava.priority).toVector.sortBy(- _._1).map{ case (k,vs) => - s"${priorityName(k)} {" +: - s" import functionConverterImpls._" +: - s" " +: - vs.map(_.implicitToJava.lines).mkVec().indent :+ - s"}" - } - val explicitDefs = codes.map(_.defs).mkVecVec() - val packageObj = - s"${priorityName(0)} {" +: - s" import functionConverterImpls._" +: - s" " +: - { - explicitDefs.indent ++ - Vector.fill(3)(" ") ++ - codes.filter(_.implicitToJava.priority == 0).map(_.implicitToJava.lines).mkVec().indent ++ - Vector.fill(3)(" ") ++ - codes.map(_.implicitToScala).mkVec().indent - } :+ "}" - (impls, traits :+ packageObj) - } - } - - private def buildWrappersViaReflection: Seq[SamConversionCode] = { - - val pack: Symbol = rootMirror.getPackageIfDefined("java.util.function") - - case class Jfn(iface: Symbol, sam: Symbol) { - lazy val genericCount = iface.typeParams.length - lazy val name = sam.name.toTermName - lazy val title = iface.name.encoded - lazy val params = sam.info.params - lazy val sig = sam typeSignatureIn iface.info - lazy val pTypes = sig.params.map(_.info) - lazy val rType = sig.resultType - def arity = params.length - } - - val sams = pack.info.decls. - map(d => (d, d.typeSignature.members.filter(_.isAbstract).toList)). - collect{ case (d, m :: Nil) if d.isAbstract => Jfn(d, m) } - - def generate(jfn: Jfn): SamConversionCode = { - def mkRef(tp: Type): Tree = if (tp.typeSymbol.isTypeParameter) Ident(tp.typeSymbol.name.toTypeName) else tq"$tp" - - // Types for the Java SAM and the corresponding Scala function, plus all type parameters - val scalaType = gen.mkAttributedRef(FunctionClass(jfn.arity)) - val javaType = gen.mkAttributedRef(jfn.iface) - val tnParams: List[TypeName] = jfn.iface.typeParams.map(_.name.toTypeName) - val tdParams: List[TypeDef] = tnParams.map(TypeDef(NoMods, _, Nil, EmptyTree)) - val javaTargs: List[Tree] = tdParams.map(_.name).map(Ident(_)) - val scalaTargs: List[Tree] = jfn.pTypes.map(mkRef) :+ mkRef(jfn.rType) - - // Conversion wrappers have three or four components that we need to name - // (1) The wrapper class that wraps a Java SAM as Scala function, or vice versa (ClassN) - // (2) A value class that provides .asJava or .asScala to request the conversion (ValCN) - // (3) A name for an explicit conversion method (DefN) - // (4) An implicit conversion method name (ImpN) that invokes the value class - - // Names for Java conversions to Scala - val j2sClassN = TypeName("FromJava" + jfn.title) - val j2sValCN = TypeName("Rich" + jfn.title + "As" + scalaType.name.encoded) - val j2sDefN = TermName("asScalaFrom" + jfn.title) - val j2sImpN = TermName("enrichAsScalaFrom" + jfn.title) - - // Names for Scala conversions to Java - val s2jClassN = TypeName("AsJava" + jfn.title) - val s2jValCN = TypeName("Rich" + scalaType.name.encoded + "As" + jfn.title) - val s2jDefN = TermName("asJava" + jfn.title) - val s2jImpN = TermName("enrichAsJava" + jfn.title) - - // Argument lists for the function / SAM - val vParams = (jfn.params zip jfn.pTypes).map{ case (p,t) => - ValDef(NoMods, p.name.toTermName, if (t.typeSymbol.isTypeParameter) Ident(t.typeSymbol.name) else gen.mkAttributedRef(t.typeSymbol), EmptyTree) - } - val vParamRefs = vParams.map(_.name).map(Ident(_)) - - val j2sClassTree = - q"""class $j2sClassN[..$tdParams](jf: $javaType[..$javaTargs]) extends $scalaType[..$scalaTargs] { - def apply(..$vParams) = jf.${jfn.name}(..$vParamRefs) - }""" - - val j2sValCTree = - q"""class $j2sValCN[..$tdParams](private val underlying: $javaType[..$javaTargs]) extends AnyVal { - @inline def asScala: $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](underlying) - }""" - - val j2sDefTree = - q"""@inline def $j2sDefN[..$tdParams](jf: $javaType[..$javaTargs]): $scalaType[..$scalaTargs] = new $j2sClassN[..$tnParams](jf)""" - - val j2sImpTree = - q"""@inline implicit def $j2sImpN[..$tdParams](jf: $javaType[..$javaTargs]): $j2sValCN[..$tnParams] = new $j2sValCN[..$tnParams](jf)""" - - val s2jClassTree = - q"""class $s2jClassN[..$tdParams](sf: $scalaType[..$scalaTargs]) extends $javaType[..$javaTargs] { - def ${jfn.name}(..$vParams) = sf.apply(..$vParamRefs) - }""" - - val s2jValCTree = - q"""class $s2jValCN[..$tdParams](private val underlying: $scalaType[..$scalaTargs]) extends AnyVal { - @inline def asJava: $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](underlying) - }""" - - val s2jDefTree = - q"""@inline def $s2jDefN[..$tdParams](sf: $scalaType[..$scalaTargs]): $javaType[..$javaTargs] = new $s2jClassN[..$tnParams](sf)""" - - // This is especially tricky because functions are contravariant in their arguments - // Need to prevent e.g. Any => String from "downcasting" itself to Int => String; we want the more exact conversion - val s2jImpTree: (Tree, Int) = - if (jfn.pTypes.forall(! _.isFinalType) && jfn.sig == jfn.sam.typeSignature) - ( - q"""@inline implicit def $s2jImpN[..$tdParams](sf: $scalaType[..$scalaTargs]): $s2jValCN[..$tnParams] = new $s2jValCN[..$tnParams](sf)""", - tdParams.length - ) - else { - // Some types are not generic or are re-used; we had better catch those. - // Making up new type names, so switch everything to TypeName or TypeDef - // Instead of foo[A](f: (Int, A) => Long): Fuu[A] = new Foo[A](f) - // we want foo[X, A](f: (X, A) => Long)(implicit evX: Int =:= X): Fuu[A] = new Foo[A](f.asInstanceOf[(Int, A) => Long]) - // Instead of bar[A](f: A => A): Brr[A] = new Foo[A](f) - // we want bar[A, B](f: A => B)(implicit evB: A =:= B): Brr[A] = new Foo[A](f.asInstanceOf[A => B]) - val An = "A(\\d+)".r - val numberedA = collection.mutable.Set.empty[Int] - val evidences = collection.mutable.ArrayBuffer.empty[(TypeName, TypeName)] - numberedA ++= scalaTargs.map(_.toString).collect{ case An(digits) if (digits.length < 10) => digits.toInt } - val scalafnTnames = (jfn.pTypes :+ jfn.rType).zipWithIndex.map{ - case (pt, i) if (i < jfn.pTypes.length && pt.isFinalType) || (!pt.isFinalType && jfn.pTypes.take(i).exists(_ == pt)) => - val j = Iterator.from(i).dropWhile(numberedA).next() - val genericName = TypeName(s"A$j") - numberedA += j - evidences += ((genericName, pt.typeSymbol.name.toTypeName)) - genericName - case (pt, _) => pt.typeSymbol.name.toTypeName - } - val scalafnTdefs = scalafnTnames. - map(TypeDef(NoMods, _, Nil, EmptyTree)). - dropRight(if (jfn.rType.isFinalType) 1 else 0) - val evs = evidences.map{ case (generic, specific) => ValDef(NoMods, TermName("ev"+generic.toString), tq"$generic =:= $specific", EmptyTree) } - val tree = - q"""@inline implicit def $s2jImpN[..$scalafnTdefs](sf: $scalaType[..$scalafnTnames])(implicit ..$evs): $s2jValCN[..$tnParams] = - new $s2jValCN[..$tnParams](sf.asInstanceOf[$scalaType[..$scalaTargs]]) - """ - (tree, tdParams.length) - } - - SamConversionCode( - base = jfn.title, - wrappedAsScala = j2sClassTree.text, - asScalaAnyVal = j2sValCTree.text, - implicitToScala = j2sImpTree.text, - asScalaDef = j2sDefTree.text, - wrappedAsJava = s2jClassTree.text, - asJavaAnyVal = s2jValCTree.text, - implicitToJava = s2jImpTree match { case (t,d) => Prioritized(t.text, d) }, - asJavaDef = s2jDefTree.text - ) - } - - sams.toSeq.map(generate) - } - - lazy val converterContents = - s""" - |$copyright - | - |$packaging - | - |import language.implicitConversions - | - | - |""".stripMargin + - (SamConversionCode(buildWrappersViaReflection: _*) match { - case (impls, defs) => impls.mkString("\n") + "\n\n\n\n" + defs.map(_.mkString("\n")).mkString("\n\n\n\n") - }) - - def sameText(f: java.io.File, text: String): Boolean = { - val x = scala.io.Source.fromFile(f) - val lines = try { x.getLines.toVector } finally { x.close } - lines.iterator.filter(_.nonBlank) == text.linesIterator.filter(_.nonBlank) - } - - def write(f: java.io.File, text: String): Unit = { - if (!f.exists || !sameText(f, text)) { - val p = new java.io.PrintWriter(f) - try { p.println(text) } - finally { p.close() } - } - } - - def main(args: Array[String]): Unit = { - val names = args.iterator.map(x => new java.io.File(x)) - write(names.next(), converterContents) - } -} From 61c7b16b9915d99ab62dd32dd3f3e45d1b7407b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bu=CC=80i=20Vie=CC=A3=CC=82t=20Tha=CC=80nh?= Date: Fri, 1 Jan 2021 09:08:53 +0700 Subject: [PATCH 261/340] sbt: Remove mima filters & disable mima against v<=1.0.1 --- build.sbt | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/build.sbt b/build.sbt index fbca7af..c0726b2 100644 --- a/build.sbt +++ b/build.sbt @@ -65,17 +65,11 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", - mimaBinaryIssueFilters ++= { - import com.typesafe.tools.mima.core._, ProblemFilters._ - Seq( - // bah - exclude[IncompatibleSignatureProblem]("*"), - // mysterious -- see scala/scala-java8-compat#211 - exclude[DirectMissingMethodProblem ]("scala.compat.java8.Priority1FunctionConverters.enrichAsJavaIntFunction"), - exclude[ReversedMissingMethodProblem]("scala.compat.java8.Priority1FunctionConverters.enrichAsJavaIntFunction"), - exclude[DirectMissingMethodProblem ]("scala.compat.java8.FunctionConverters.package.enrichAsJavaIntFunction" ), - exclude[ReversedMissingMethodProblem]("scala.compat.java8.FunctionConverters.package.enrichAsJavaIntFunction" ), - ) + // see https://github.com/scala/scala-java8-compat/issues/247 + versionPolicyPreviousVersions := versionPolicyPreviousVersions.value.flatMap { + case VersionNumber(Seq(0, _*), _, _) => Nil + case VersionNumber(Seq(1, 0, n, _*), _, _) if n <= 1 => Nil + case v => Seq(v) }, testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), From 29cb343302639600d59877cfc797f9b754f3210a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bu=CC=80i=20Vie=CC=A3=CC=82t=20Tha=CC=80nh?= Date: Tue, 5 Oct 2021 16:13:35 +0700 Subject: [PATCH 262/340] Add test case for issue #247 --- .../scala/compat/java8/Issue247Test.scala | 83 +++++++++++++++++++ .../scala/compat/java8/issue247/Main.scala | 27 ++++++ 2 files changed, 110 insertions(+) create mode 100644 src/test/scala/scala/compat/java8/Issue247Test.scala create mode 100644 src/test/scala/scala/compat/java8/issue247/Main.scala diff --git a/src/test/scala/scala/compat/java8/Issue247Test.scala b/src/test/scala/scala/compat/java8/Issue247Test.scala new file mode 100644 index 0000000..6a2ddc0 --- /dev/null +++ b/src/test/scala/scala/compat/java8/Issue247Test.scala @@ -0,0 +1,83 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8 + +import org.junit.Assert._ +import org.junit.Assume.assumeTrue +import org.junit.Test +import org.junit.function.ThrowingRunnable + +import java.nio.file.{Files, Paths} +import scala.compat.java8.StreamConverters._ +import scala.compat.java8.issue247.Main +import scala.sys.process._ +import scala.util.Try + +class Issue247Test { + @Test + def runMainDirectly(): Unit = Main.main(Array.empty) + + val mainCls = "scala.compat.java8.issue247.Main" + + @Test + def runMainMatrix(): Unit = { + assumeTrue("only run in Linux/OSX", "which which".! == 0) + + val pwd = "pwd".!!.trim + + val coursier = Try { + ("which cs" #|| "which coursier").!!.trim + }.getOrElse { + val cs = s"$pwd/target/coursier" + if (!Files.isExecutable(Paths.get(cs))) + ( s"curl -fLo $cs https://git.io/coursier-cli" #&& + s"chmod +x $cs" + ).!.ensuring(_ == 0) + cs + } + + for { + scalaBinV <- Seq("2.11", "2.12", "2.13", "3") + compatV <- Seq("0.9.1", "1.0.0", "1.0.1") + // scala-java8-compat for scala3 don't have version 0.9.1 + if scalaBinV != "3" || compatV != "0.9.1" + scalaDir <- Files.list(Paths.get(pwd, "target")).toScala[List] + if scalaDir.toFile.getName.startsWith(s"scala-$scalaBinV") + classesDir = scalaDir.resolve("test-classes") + if classesDir.resolve("scala/compat/java8/issue247/Main.class").toFile.isFile + } { + val classpath = Process( + Seq( + coursier, // may contain spaces + "fetch", "--classpath", + s"org.scala-lang.modules:scala-java8-compat_$scalaBinV:$compatV" + ) + ).!!.trim + + val testCmd = s"java -cp $classpath:$classesDir $mainCls" + + val run: ThrowingRunnable = new ThrowingRunnable { + def run(): Unit = { + println(testCmd) + testCmd.!! + } + } + + if ((scalaBinV, compatV) == ("2.13", "0.9.1")) { + run.run() // no Exception + } else { + assertThrows(classOf[RuntimeException], run) + } + } + } +} diff --git a/src/test/scala/scala/compat/java8/issue247/Main.scala b/src/test/scala/scala/compat/java8/issue247/Main.scala new file mode 100644 index 0000000..25fcc29 --- /dev/null +++ b/src/test/scala/scala/compat/java8/issue247/Main.scala @@ -0,0 +1,27 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.compat.java8.issue247 + +import scala.compat.java8.FunctionConverters._ +import java.util.function.IntFunction + +object Main { + def invoke(jfun: IntFunction[String]): String = jfun(2) + + def main(args: Array[String]): Unit = { + val sfun = (i: Int) => s"ret: $i" + val ret = invoke(sfun.asJava) + assert(ret == "ret: 2") + println(s"OK. $ret") + } +} From 84f679e86db17a610d635a16de341e2b6d9ed16e Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 26 Oct 2021 07:00:10 +0200 Subject: [PATCH 263/340] Update junit-interface to 0.13.2 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7c82719..e5bcf26 100644 --- a/build.sbt +++ b/build.sbt @@ -75,7 +75,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.12.0" % "test", - libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test", + libraryDependencies += "com.github.sbt" % "junit-interface" % "0.13.2" % "test", mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._, ProblemFilters._ From 0478d7d411e3d3c21508e113915b46a3aba6d729 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 1 Nov 2021 19:30:41 +0100 Subject: [PATCH 264/340] Update scala-library to 2.13.7 --- .github/workflows/ci.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 932ecdb..06e2029 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: java: [8, 11, 17] - scala: [2.11.12, 2.12.15, 2.13.6, 3.0.2] + scala: [2.11.12, 2.12.15, 2.13.7, 3.0.2] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/build.sbt b/build.sbt index 29e709b..64ed403 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ def osgiExport(scalaVersion: String, version: String) = { ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.6", "2.12.15", "2.11.12", "3.0.2"), + crossScalaVersions := Seq("2.13.7", "2.12.15", "2.11.12", "3.0.2"), scalaVersion := crossScalaVersions.value.head, versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { From 1ada529584fa658def6f6d12c0c0f90f3485cd16 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 10 Dec 2021 21:37:07 +0100 Subject: [PATCH 265/340] Update sbt to 1.5.6 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 10fd9ee..bb3a9b7 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.5 +sbt.version=1.5.6 From ab302d0c3465aed96542c024d986d421f0d669ed Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 16 Dec 2021 11:13:35 +0100 Subject: [PATCH 266/340] Update sbt to 1.5.7 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index bb3a9b7..baf5ff3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.6 +sbt.version=1.5.7 From fe65794dc4813aeeb65dee2c5da0d43c18b8afd9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 21 Dec 2021 20:27:19 +0100 Subject: [PATCH 267/340] Update sbt to 1.5.8 (#257) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index baf5ff3..e64c208 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.7 +sbt.version=1.5.8 From 36e1f61b5dfe438353562c57e9bbbacbd3970e57 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 27 Dec 2021 08:34:49 +0100 Subject: [PATCH 268/340] Update sbt to 1.6.0 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e64c208..1e70b0c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.8 +sbt.version=1.6.0 From 94ec42d11793cb15cbf3eb87f8690cab3ef45051 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 29 Dec 2021 21:34:16 +0100 Subject: [PATCH 269/340] Update sbt to 1.6.1 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 1e70b0c..3161d21 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.6.0 +sbt.version=1.6.1 From cfe6278cd9a516d02f50059e638484e0399d45c1 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 29 Dec 2021 21:34:12 +0100 Subject: [PATCH 270/340] Update junit-interface to 0.13.3 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 64ed403..acdc337 100644 --- a/build.sbt +++ b/build.sbt @@ -63,7 +63,7 @@ lazy val scalaJava8Compat = (project in file(".")) libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.12.0" % "test", - libraryDependencies += "com.github.sbt" % "junit-interface" % "0.13.2" % "test", + libraryDependencies += "com.github.sbt" % "junit-interface" % "0.13.3" % "test", // see https://github.com/scala/scala-java8-compat/issues/247 versionPolicyPreviousVersions := versionPolicyPreviousVersions.value.flatMap { From fd7a8cf136417b8d957123740d17060c01ce4d39 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 5 Jan 2022 16:06:20 -0800 Subject: [PATCH 271/340] copyright 2022 --- NOTICE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE b/NOTICE index a076f57..ceba0e4 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,6 @@ scala-java8-compat -Copyright (c) 2002-2021 EPFL -Copyright (c) 2011-2021 Lightbend, Inc. +Copyright (c) 2002-2022 EPFL +Copyright (c) 2011-2022 Lightbend, Inc. scala-java8-compat includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and From df8f046ea225cbb9a2fd4b2dc5085397cd6887d5 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 6 Jan 2022 09:09:12 +0100 Subject: [PATCH 272/340] Update sbt-scala-module to 3.0.1 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index a668f72..d8d97fc 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.0.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.0.1") From 372fe5a1a0461767e40c6956b0d2d90d709af21a Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 14 Jan 2022 02:56:05 +0100 Subject: [PATCH 273/340] Update scala-library to 2.13.8 (#262) --- .github/workflows/ci.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06e2029..8ac3387 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: java: [8, 11, 17] - scala: [2.11.12, 2.12.15, 2.13.7, 3.0.2] + scala: [2.11.12, 2.12.15, 2.13.8, 3.0.2] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/build.sbt b/build.sbt index acdc337..f606bef 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ def osgiExport(scalaVersion: String, version: String) = { ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.7", "2.12.15", "2.11.12", "3.0.2"), + crossScalaVersions := Seq("2.13.8", "2.12.15", "2.11.12", "3.0.2"), scalaVersion := crossScalaVersions.value.head, versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { From ff64b0109e9445e71f9d7c66fd230be5d12d053b Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 2 Feb 2022 07:53:53 +0100 Subject: [PATCH 274/340] Update sbt to 1.6.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 3161d21..c8fcab5 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.6.1 +sbt.version=1.6.2 From 6b31440f2218011b2202cbabcfa63ce908d24148 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 28 Jun 2022 22:50:23 +0000 Subject: [PATCH 275/340] Update scala-library to 2.12.16 --- .github/workflows/ci.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ac3387..fb4922b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: java: [8, 11, 17] - scala: [2.11.12, 2.12.15, 2.13.8, 3.0.2] + scala: [2.11.12, 2.12.16, 2.13.8, 3.0.2] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/build.sbt b/build.sbt index f606bef..2df392d 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ def osgiExport(scalaVersion: String, version: String) = { ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.8", "2.12.15", "2.11.12", "3.0.2"), + crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.0.2"), scalaVersion := crossScalaVersions.value.head, versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { From 47bac303e6935352c1184cb338d3b319276f4e5d Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:10:17 +0200 Subject: [PATCH 276/340] Update sbt to 1.7.1 (#268) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index c8fcab5..22af262 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.6.2 +sbt.version=1.7.1 From b5b91a83265eb525d0c523ad5379f156ab11a679 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 28 Jun 2022 22:50:27 +0000 Subject: [PATCH 277/340] Update scala3-library to 3.1.3 --- .github/workflows/ci.yml | 2 +- build.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb4922b..799d425 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: java: [8, 11, 17] - scala: [2.11.12, 2.12.16, 2.13.8, 3.0.2] + scala: [2.11.12, 2.12.16, 2.13.8, 3.1.3] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/build.sbt b/build.sbt index 2df392d..92d287d 100644 --- a/build.sbt +++ b/build.sbt @@ -23,7 +23,7 @@ def osgiExport(scalaVersion: String, version: String) = { ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.0.2"), + crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.1.3"), scalaVersion := crossScalaVersions.value.head, versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, Compile / unmanagedSourceDirectories ++= { From 499fc0614c82c2c8d40a6758cf343b9fad2e94a2 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Jul 2022 11:11:11 -0700 Subject: [PATCH 278/340] simplify CI config using new sbt 1.7 feature --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 799d425..8dc1bd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: java: [8, 11, 17] - scala: [2.11.12, 2.12.16, 2.13.8, 3.1.3] + scala: [2.11.x, 2.12.x, 2.13.x, 3.x] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From 0963ad840dd4a83719d2bf5e70a60216d893f57d Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Jul 2022 11:14:58 -0700 Subject: [PATCH 279/340] remove unnecessary workaround from build --- build.sbt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build.sbt b/build.sbt index 92d287d..c7e635d 100644 --- a/build.sbt +++ b/build.sbt @@ -18,10 +18,6 @@ def osgiExport(scalaVersion: String, version: String) = { }) ++ Seq(s"scala.compat.java8.*;version=${version}") } -// shouldn't be necessary anymore after https://github.com/lampepfl/dotty/pull/13498 -// makes it into a release -ThisBuild / libraryDependencySchemes += "org.scala-lang" %% "scala3-library" % "semver-spec" - lazy val commonSettings = Seq( crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.1.3"), scalaVersion := crossScalaVersions.value.head, From ccf3550bb223568823add14efc6cc0e7603a64bd Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Jul 2022 11:29:58 -0700 Subject: [PATCH 280/340] make MiMa okay with the Scala 3.0->3.1 upgrade --- build.sbt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c7e635d..fa2fc10 100644 --- a/build.sbt +++ b/build.sbt @@ -21,7 +21,9 @@ def osgiExport(scalaVersion: String, version: String) = { lazy val commonSettings = Seq( crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.1.3"), scalaVersion := crossScalaVersions.value.head, - versionPolicyIntention := Compatibility.BinaryAndSourceCompatible, + // we could make this stricter again (BinaryAndSourceCompatible) + // after our reference version was built on Scala 3.1.x + versionPolicyIntention := Compatibility.BinaryCompatible, Compile / unmanagedSourceDirectories ++= { (Compile / unmanagedSourceDirectories).value.flatMap { dir => CrossVersion.partialVersion(scalaVersion.value) match { @@ -68,6 +70,17 @@ lazy val scalaJava8Compat = (project in file(".")) case v => Seq(v) }, + // shouldn't be needed anymore after our reference version is a version + // built on Scala 3.1.x + mimaBinaryIssueFilters := { + import com.typesafe.tools.mima.core.ProblemFilters._ + import com.typesafe.tools.mima.core._ + Seq( + exclude[IncompatibleSignatureProblem]("scala.compat.java8.*"), + exclude[IncompatibleSignatureProblem]("scala.concurrent.java8.*"), + ), + }, + testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), (Compile / sourceGenerators) += Def.task { From e5a9188899d930d207898f7ae650afc822fe2dbf Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Jul 2022 11:41:38 -0700 Subject: [PATCH 281/340] CI: do full publishLocal in checks in the hopes of catching doc generation issues during PR validation (genjavadoc is especially fragile) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8dc1bd0..1eff535 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,4 +22,4 @@ jobs: distribution: temurin java-version: ${{matrix.java}} - name: Test - run: sbt ++${{matrix.scala}} test headerCheck versionPolicyCheck package + run: sbt ++${{matrix.scala}} test headerCheck versionPolicyCheck publishLocal From a233b48cef1304be10346c6480b7af103f4b79f0 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 14 Jul 2022 11:53:05 -0700 Subject: [PATCH 282/340] re-enable Scaladoc generation on Scala 3 it used to be broken but now it works --- build.sbt | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.sbt b/build.sbt index fa2fc10..824c411 100644 --- a/build.sbt +++ b/build.sbt @@ -115,8 +115,6 @@ lazy val scalaJava8Compat = (project in file(".")) if (Set("1.5", "1.6", "1.7") contains specVersion) sys.error("Java 8 or higher is required for this project.") }, - - packageDoc / publishArtifact := !disableDocs && !scalaVersion.value.startsWith("3.") ) .settings( inConfig(JavaDoc)(Defaults.configSettings) ++ { From fbbd6d4c441829a6c7e5644d686fe4af13b74f1a Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 15 Oct 2022 09:34:51 +0000 Subject: [PATCH 283/340] Update sbt to 1.7.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 22af262..563a014 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.7.1 +sbt.version=1.7.2 From d8dd8c149c61a29ce3694c8f149cca0bb05ed81c Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 18 Oct 2022 21:46:31 +0200 Subject: [PATCH 284/340] Update scala-library to 2.12.17 (#270) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 824c411..80fe815 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.8", "2.12.16", "2.11.12", "3.1.3"), + crossScalaVersions := Seq("2.13.8", "2.12.17", "2.11.12", "3.1.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From be5b1332100a68cef2adcc8bc6511dce086ada94 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 18 Oct 2022 21:56:10 +0200 Subject: [PATCH 285/340] Update scala-library to 2.13.10 (#271) Co-authored-by: Seth Tisue --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 80fe815..5505047 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.8", "2.12.17", "2.11.12", "3.1.3"), + crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.1.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 295255b51ab50c372c4a21c46b5e1c337974909a Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sun, 6 Nov 2022 21:27:44 +0000 Subject: [PATCH 286/340] Update sbt to 1.7.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 563a014..6a9f038 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.7.2 +sbt.version=1.7.3 From 4f110dcabcf7f89063acf62d9868d86c84cade24 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sun, 20 Nov 2022 19:41:16 +0000 Subject: [PATCH 287/340] Update sbt to 1.8.0 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6a9f038..8b9a0b0 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.7.3 +sbt.version=1.8.0 From 383e6d13e6a3a0b84e01b2010912cb7c54c61dbb Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 9 Dec 2022 01:58:26 +0100 Subject: [PATCH 288/340] Update scala3-library to 3.2.1 (#274) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5505047..7bcfbe1 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.1.3"), + crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.2.1"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 41c644881365f237b57e25e2780e605a92782a10 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 5 Jan 2023 20:37:16 +0000 Subject: [PATCH 289/340] Update sbt to 1.8.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 8b9a0b0..46e43a9 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.0 +sbt.version=1.8.2 From f678d279e6c01ade4c95dad536e33dffe2fa8aba Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Mon, 9 Jan 2023 21:06:04 -0800 Subject: [PATCH 290/340] copyright 2023 (#277) --- NOTICE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NOTICE b/NOTICE index ceba0e4..97387ff 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,6 @@ scala-java8-compat -Copyright (c) 2002-2022 EPFL -Copyright (c) 2011-2022 Lightbend, Inc. +Copyright (c) 2002-2023 EPFL +Copyright (c) 2011-2023 Lightbend, Inc. scala-java8-compat includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and From fa0eb3f858e28f49612780fb61661a2bde271892 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 13 Feb 2023 21:25:25 +0100 Subject: [PATCH 291/340] Update scala3-library to 3.2.2 (#278) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 7bcfbe1..c358886 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.2.1"), + crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.2.2"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 06c880296cd351bf5695f098e852ac081bbc6703 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 25 May 2023 08:51:15 +0000 Subject: [PATCH 292/340] Update sbt to 1.8.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 46e43a9..72413de 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.2 +sbt.version=1.8.3 From 70677c7172f9d1b7622ab98a1a893616d47855b5 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 30 Jun 2023 23:53:23 +0000 Subject: [PATCH 293/340] Update sbt to 1.9.1 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 72413de..3c0b78a 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.3 +sbt.version=1.9.1 From a1a5524264c3dd27de01c18a36d86bbfc4d2b8af Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sat, 1 Jul 2023 17:06:36 +0200 Subject: [PATCH 294/340] Update scala-library to 2.12.18 (#282) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index c358886..9fb5a80 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.10", "2.12.17", "2.11.12", "3.2.2"), + crossScalaVersions := Seq("2.13.10", "2.12.18", "2.11.12", "3.2.2"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 2c9a4a6e4558826e40f2a8278b5bd3ec2ddccf57 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 3 Jul 2023 15:37:16 +0200 Subject: [PATCH 295/340] Update scala3-library to 3.3.0 (#280) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9fb5a80..2d1461d 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.10", "2.12.18", "2.11.12", "3.2.2"), + crossScalaVersions := Seq("2.13.10", "2.12.18", "2.11.12", "3.3.0"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 7b2fa2ae4711c065facaab132442f5385e61a6c8 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 10 Jul 2023 23:48:11 +0200 Subject: [PATCH 296/340] Update scala-library to 2.13.11 (#283) Co-authored-by: Seth Tisue --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 2d1461d..9116383 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.10", "2.12.18", "2.11.12", "3.3.0"), + crossScalaVersions := Seq("2.13.11", "2.12.18", "2.11.12", "3.3.0"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From a4d03c653f21793ce7d0b58765bb1a88399f025f Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Thu, 13 Jul 2023 00:01:45 +0000 Subject: [PATCH 297/340] Update sbt to 1.9.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 3c0b78a..875b706 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.1 +sbt.version=1.9.2 From 84d7a9bd454b1b17a946fa399a9e7f0df9df346f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 25 Jul 2023 19:58:19 +0200 Subject: [PATCH 298/340] Update sbt-scala-module to 3.1.0 (#285) --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index d8d97fc..f72bd52 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.0.1") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.1.0") From 258e693ef3e4f487ec72b4c72c9cb11a1fe0c846 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 26 Jul 2023 20:40:33 +0000 Subject: [PATCH 299/340] Update sbt to 1.9.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 875b706..52413ab 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.2 +sbt.version=1.9.3 From be2419bdf002854dae66f356e61e5a36e02f5584 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 26 Aug 2023 05:20:43 +0000 Subject: [PATCH 300/340] Update sbt to 1.9.4 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 52413ab..3040987 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.3 +sbt.version=1.9.4 From 952d94cd5739db8e9981678718f3a0614a5b8af3 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 18 Sep 2023 21:59:37 +0000 Subject: [PATCH 301/340] Update sbt to 1.9.6 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 3040987..2743082 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.4 +sbt.version=1.9.6 From 76436b7f27283964b310563f9b6659d3ed8fcd16 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 13 Sep 2023 02:50:36 +0000 Subject: [PATCH 302/340] Update scala-library to 2.13.12 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9116383..aac8a06 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.11", "2.12.18", "2.11.12", "3.3.0"), + crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.0"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 3159cea253c00070506b393e1270cf9e7791fd88 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Mon, 9 Oct 2023 03:31:36 +0200 Subject: [PATCH 303/340] Update scala3-library to 3.3.1 (#290) * Update scala3-library to 3.3.1 * Revert commit(s) 156a0cb * Update scala3-library to 3.3.1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index aac8a06..d07f396 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.0"), + crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.1"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From bf4e4ef8914a8c62480b00306a653273b5989d27 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 25 Oct 2023 05:01:15 +0000 Subject: [PATCH 304/340] Update sbt to 1.9.7 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 2743082..e8a1e24 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.6 +sbt.version=1.9.7 From fd1ad0b790900ce81ad99331c0738ff1d6b3ed8e Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 16 Jan 2024 04:03:32 +0100 Subject: [PATCH 305/340] Update sbt to 1.9.8 (#295) --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e8a1e24..abbbce5 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.7 +sbt.version=1.9.8 From cb0206c1cf3ea1a90ecfec3f098595b017870813 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 24 Feb 2024 00:05:18 +0000 Subject: [PATCH 306/340] Update sbt to 1.9.9 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index abbbce5..04267b1 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.8 +sbt.version=1.9.9 From bcc4cc9ec85351b8a375f5d1ccfb82f2443f007c Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Sun, 17 Mar 2024 22:13:35 +0100 Subject: [PATCH 307/340] Add java 21 to build matrix (#301) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1eff535..32975a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - java: [8, 11, 17] + java: [8, 11, 17, 21] scala: [2.11.x, 2.12.x, 2.13.x, 3.x] runs-on: ubuntu-latest steps: From 6cd5dec50b838cedbdd7c37fe732033cd7f41347 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Thu, 28 Mar 2024 12:42:44 +0100 Subject: [PATCH 308/340] Update checkout and setup-java github actions to v4 (#300) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32975a8..2f27907 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,11 +13,11 @@ jobs: scala: [2.11.x, 2.12.x, 2.13.x, 3.x] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: coursier/cache-action@v6 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: ${{matrix.java}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d69ab72..57aa9dd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,10 +6,10 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 From 660552cbf472349e5275e0a9b95f48d4c1d05c41 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 21 Apr 2024 23:00:35 +0200 Subject: [PATCH 309/340] Update scala3-library to 3.3.3 (#299) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d07f396..74e1fc9 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.1"), + crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 650ac0e64d8261a2e0f620467d7aed3185978940 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Sun, 21 Apr 2024 23:04:15 +0200 Subject: [PATCH 310/340] Update scala-library to 2.13.13 (#298) Co-authored-by: Seth Tisue --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 74e1fc9..49c10fb 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.12", "2.12.18", "2.11.12", "3.3.3"), + crossScalaVersions := Seq("2.13.13", "2.12.18", "2.11.12", "3.3.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From a594aee58740b92863c85710279a1692194e454e Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 8 May 2024 06:00:20 +0000 Subject: [PATCH 311/340] Update sbt to 1.10.0 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 04267b1..081fdbb 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.9 +sbt.version=1.10.0 From 2bf2c3a760a889ae53bf5f47f371fb96c26616b9 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 21 May 2024 18:04:04 +0200 Subject: [PATCH 312/340] Update scala-library to 2.12.19 (#297) Co-authored-by: Seth Tisue --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 49c10fb..d24fef7 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.13", "2.12.18", "2.11.12", "3.3.3"), + crossScalaVersions := Seq("2.13.13", "2.12.19", "2.11.12", "3.3.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 98c44d673eafb9044516ec33bcff1047fbe4801a Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 10 Jul 2024 20:42:15 +0000 Subject: [PATCH 313/340] Update sbt to 1.10.1 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 081fdbb..ee4c672 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.0 +sbt.version=1.10.1 From db3c440ca3c72fe16265a030078c22c941632660 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 8 Aug 2024 17:33:59 -0700 Subject: [PATCH 314/340] Steward, don't update commons-lang3 (#307) --- .scala-steward.conf | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .scala-steward.conf diff --git a/.scala-steward.conf b/.scala-steward.conf new file mode 100644 index 0000000..4b6a192 --- /dev/null +++ b/.scala-steward.conf @@ -0,0 +1,4 @@ +updates.ignore = [ + # see https://github.com/scala/scala-java8-compat/pull/306 + { groupId = "org.apache.commons", artifactId = "commons-lang3" } +] From 848cdfac5f83f743cfecfed876f04c1e5e435638 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 8 Aug 2024 17:40:05 -0700 Subject: [PATCH 315/340] genjavadoc 0.19 (was 0.18) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d24fef7..8e0af87 100644 --- a/build.sbt +++ b/build.sbt @@ -131,7 +131,7 @@ lazy val scalaJava8Compat = (project in file(".")) JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() - case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.18" cross CrossVersion.full)) + case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.19" cross CrossVersion.full)) }), Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() From e51ccf8565260cbf4572bbbc802613892eae2579 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Thu, 8 Aug 2024 17:58:07 -0700 Subject: [PATCH 316/340] genjavadoc 0.18 was the final version for Scala 2.11 --- build.sbt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 8e0af87..92e23dd 100644 --- a/build.sbt +++ b/build.sbt @@ -130,8 +130,9 @@ lazy val scalaJava8Compat = (project in file(".")) JavaDoc / javacOptions := Seq("-Xdoclint:none"), JavaDoc / packageDoc / artifactName := ((sv, mod, art) => "" + mod.name + "_" + sv.binary + "-" + mod.revision + "-javadoc.jar"), libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match { - case Some((3, _)) => Seq() - case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.19" cross CrossVersion.full)) + case Some((3, _)) => Seq() + case Some((2, 11)) => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.18" cross CrossVersion.full)) + case _ => Seq(compilerPlugin("com.typesafe.genjavadoc" % "genjavadoc-plugin" % "0.19" cross CrossVersion.full)) }), Compile / scalacOptions ++= (CrossVersion.partialVersion(scalaVersion.value) match { case Some((3, _)) => Seq() From f0944889469c188a899e713487862a1827c4180f Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:12:17 +0200 Subject: [PATCH 317/340] Update scala-library to 2.13.14 (#302) Co-authored-by: Seth Tisue --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 92e23dd..ff2daf6 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.13", "2.12.19", "2.11.12", "3.3.3"), + crossScalaVersions := Seq("2.13.14", "2.12.19", "2.11.12", "3.3.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 8cb0491d17f48271b7c134c7977ed51a9c1e24b2 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 16 Sep 2024 18:56:43 +0000 Subject: [PATCH 318/340] Update sbt to 1.10.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index ee4c672..0b699c3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.1 +sbt.version=1.10.2 From 3dbe37b5252459cbbba58d50cd103d610bedad42 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 6 Sep 2024 18:08:59 +0000 Subject: [PATCH 319/340] Update scala-library to 2.12.20 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index ff2daf6..9003d6d 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.14", "2.12.19", "2.11.12", "3.3.3"), + crossScalaVersions := Seq("2.13.14", "2.12.20", "2.11.12", "3.3.3"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 14e79f4ed24050f468ad910e15e6efec726b1f21 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sun, 20 Oct 2024 21:57:26 +0000 Subject: [PATCH 320/340] Update sbt to 1.10.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 0b699c3..bc73906 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.2 +sbt.version=1.10.3 From eeb3cc1c5028c075b96e243422a1cde634c0f73c Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 28 Oct 2024 19:38:29 +0000 Subject: [PATCH 321/340] Update sbt, scripted-plugin to 1.10.4 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index bc73906..09feeee 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.3 +sbt.version=1.10.4 From 4fec93ed40bdc974d70c6b3abddcd97800c40d78 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 6 Nov 2024 02:00:34 +0000 Subject: [PATCH 322/340] Update sbt, scripted-plugin to 1.10.5 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 09feeee..db1723b 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.4 +sbt.version=1.10.5 From 757eb9c43227bddbcdcdd8eb5ebeb1a92185bb1a Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Mon, 2 Dec 2024 01:31:44 +0000 Subject: [PATCH 323/340] Update sbt, scripted-plugin to 1.10.6 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index db1723b..e88a0d8 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.5 +sbt.version=1.10.6 From a70331e759021da9d99c29c64fea8a71a49f44a1 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Dec 2024 08:00:45 +0900 Subject: [PATCH 324/340] add sbt/setup-sbt action --- .github/workflows/ci.yml | 1 + .github/workflows/release.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f27907..0a5b969 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,5 +21,6 @@ jobs: with: distribution: temurin java-version: ${{matrix.java}} + - uses: sbt/setup-sbt@v1 - name: Test run: sbt ++${{matrix.scala}} test headerCheck versionPolicyCheck publishLocal diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 57aa9dd..1e5360b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,7 @@ jobs: with: distribution: temurin java-version: 8 + - uses: sbt/setup-sbt@v1 - run: sbt versionCheck ci-release env: PGP_PASSPHRASE: ${{secrets.PGP_PASSPHRASE}} From c700ccd4608014e907ef3220e995652e93ab4518 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 28 Sep 2024 23:45:52 +0000 Subject: [PATCH 325/340] Update scala3-library to 3.3.4 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 9003d6d..e0bbeca 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.14", "2.12.20", "2.11.12", "3.3.3"), + crossScalaVersions := Seq("2.13.14", "2.12.20", "2.11.12", "3.3.4"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 78f3dcc725b1abea4bea1810b562e46a4313f0b3 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 25 Dec 2024 22:21:28 +0000 Subject: [PATCH 326/340] Update sbt, scripted-plugin to 1.10.7 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e88a0d8..73df629 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.6 +sbt.version=1.10.7 From 753549ea4f853894d6039cee04d1d04a15a72274 Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Tue, 7 Jan 2025 06:27:08 +0100 Subject: [PATCH 327/340] Update scala-library to 2.13.15 (#311) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e0bbeca..abeea7c 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.14", "2.12.20", "2.11.12", "3.3.4"), + crossScalaVersions := Seq("2.13.15", "2.12.20", "2.11.12", "3.3.4"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From d19789e11914685e068b87c108b139e7d2dbd741 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 21 Dec 2024 21:25:11 +0000 Subject: [PATCH 328/340] Update sbt-scala-module to 3.2.2 --- build.sbt | 1 + project/plugins.sbt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index abeea7c..b7eee4c 100644 --- a/build.sbt +++ b/build.sbt @@ -46,6 +46,7 @@ lazy val commonSettings = Seq( lazy val scalaJava8Compat = (project in file(".")) .settings(ScalaModulePlugin.scalaModuleSettings) + .enablePlugins(SbtOsgi) .settings(ScalaModulePlugin.scalaModuleOsgiSettings) .settings(commonSettings) .settings( diff --git a/project/plugins.sbt b/project/plugins.sbt index f72bd52..06d4e4f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.1.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.2.2") From c6e1dd9d8019c0e157eadd3afedd6206bfb096a3 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Tue, 7 Jan 2025 11:29:08 -0800 Subject: [PATCH 329/340] copyright 2025 --- NOTICE | 6 +++--- README.md | 2 +- .../java-2.13+/scala/compat/java8/ScalaStreamSupport.java | 2 +- .../java-2.13-/scala/compat/java8/ScalaStreamSupport.java | 2 +- .../scala/compat/java8/runtime/CollectionInternals.java | 2 +- .../java8/wrappers/IteratorPrimitiveDoubleWrapper.java | 2 +- .../compat/java8/wrappers/IteratorPrimitiveIntWrapper.java | 2 +- .../compat/java8/wrappers/IteratorPrimitiveLongWrapper.java | 2 +- .../scala/compat/java8/runtime/LambdaDeserializer.scala | 2 +- .../scala-2.13+/scala/compat/java8/StreamConverters.scala | 2 +- .../scala/compat/java8/collectionImpl/package.scala | 2 +- .../scala/compat/java8/converterImpl/Accumulates.scala | 2 +- .../compat/java8/converterImpl/AccumulatorConverters.scala | 2 +- .../compat/java8/converterImpl/StepperExtensions.scala | 2 +- .../concurrent/java8/FuturesConvertersImplCompat.scala | 2 +- .../scala/compat/java8/SpliteratorConverters.scala | 2 +- .../scala-2.13-/scala/compat/java8/StreamConverters.scala | 2 +- .../scala/compat/java8/collectionImpl/Accumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/AccumulatorLike.scala | 2 +- .../compat/java8/collectionImpl/DoubleAccumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/IntAccumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/LongAccumulator.scala | 2 +- .../scala/compat/java8/collectionImpl/Stepper.scala | 2 +- .../scala/compat/java8/converterImpl/Accumulates.scala | 2 +- .../compat/java8/converterImpl/AccumulatorConverters.scala | 2 +- .../scala/compat/java8/converterImpl/MakesSteppers.scala | 2 +- .../scala/compat/java8/converterImpl/StepConverters.scala | 2 +- .../scala/compat/java8/converterImpl/StepsArray.scala | 2 +- .../scala/compat/java8/converterImpl/StepsBitSet.scala | 2 +- .../compat/java8/converterImpl/StepsFlatHashTable.scala | 2 +- .../scala/compat/java8/converterImpl/StepsHashTable.scala | 2 +- .../scala/compat/java8/converterImpl/StepsImmHashMap.scala | 2 +- .../scala/compat/java8/converterImpl/StepsImmHashSet.scala | 2 +- .../scala/compat/java8/converterImpl/StepsIndexedSeq.scala | 2 +- .../scala/compat/java8/converterImpl/StepsIterable.scala | 2 +- .../scala/compat/java8/converterImpl/StepsIterator.scala | 2 +- .../scala/compat/java8/converterImpl/StepsLikeGapped.scala | 2 +- .../compat/java8/converterImpl/StepsLikeImmHashMap.scala | 2 +- .../scala/compat/java8/converterImpl/StepsLikeIndexed.scala | 2 +- .../compat/java8/converterImpl/StepsLikeIterator.scala | 2 +- .../scala/compat/java8/converterImpl/StepsLikeSliced.scala | 2 +- .../compat/java8/converterImpl/StepsLikeTrieIterator.scala | 2 +- .../scala/compat/java8/converterImpl/StepsLinearSeq.scala | 2 +- .../scala/compat/java8/converterImpl/StepsMap.scala | 2 +- .../scala/compat/java8/converterImpl/StepsRange.scala | 2 +- .../scala/compat/java8/converterImpl/StepsString.scala | 2 +- .../scala/compat/java8/converterImpl/StepsVector.scala | 2 +- .../scala/compat/java8/converterImpl/StepsWithTail.scala | 2 +- .../concurrent/java8/FuturesConvertersImplCompat.scala | 2 +- src/main/scala/scala/compat/java8/DurationConverters.scala | 2 +- src/main/scala/scala/compat/java8/FutureConverters.scala | 2 +- src/main/scala/scala/compat/java8/OptionConverters.scala | 2 +- .../scala/compat/java8/PrimitiveIteratorConversions.scala | 2 +- src/main/scala/scala/compat/java8/WrapperTraits.scala | 2 +- .../scala/scala/concurrent/java8/FutureConvertersImpl.scala | 2 +- 55 files changed, 57 insertions(+), 57 deletions(-) diff --git a/NOTICE b/NOTICE index 97387ff..a3069a2 100644 --- a/NOTICE +++ b/NOTICE @@ -1,10 +1,10 @@ scala-java8-compat -Copyright (c) 2002-2023 EPFL -Copyright (c) 2011-2023 Lightbend, Inc. +Copyright (c) 2002-2025 EPFL +Copyright (c) 2011-2025 Lightbend, Inc. dba Akka scala-java8-compat includes software developed at LAMP/EPFL (https://lamp.epfl.ch/) and -Lightbend, Inc. (https://www.lightbend.com/). +Akka (https://akka.io/). Licensed under the Apache License, Version 2.0 (the "License"). Unless required by applicable law or agreed to in writing, software diff --git a/README.md b/README.md index 34f30b9..15a28df 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ We do publish 2.13 and 3.0 artifacts of scala-java8-compat, but they're only int ## Maintenance status -This library is community-maintained. (The Scala team at Lightbend provides infrastructure and oversight.) +This library is community-maintained. (The Scala team at Akka provides infrastructure and oversight.) ## Functional Interfaces for Scala functions diff --git a/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java b/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java index af78ecd..2071d18 100644 --- a/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java-2.13+/scala/compat/java8/ScalaStreamSupport.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java b/src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java index bc21ca8..0aa976b 100644 --- a/src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java +++ b/src/main/java-2.13-/scala/compat/java8/ScalaStreamSupport.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java b/src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java index 473de11..330483c 100644 --- a/src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java +++ b/src/main/java-2.13-/scala/compat/java8/runtime/CollectionInternals.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java index 001699c..0007ab6 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveDoubleWrapper.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java index 0e9a6fe..ac9d72b 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveIntWrapper.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java index a78c736..e26e962 100644 --- a/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java +++ b/src/main/java/scala/compat/java8/wrappers/IteratorPrimitiveLongWrapper.java @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala b/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala index 551e649..e3ad73a 100644 --- a/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala +++ b/src/main/scala-2.11/scala/compat/java8/runtime/LambdaDeserializer.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala index 309d4c3..d977d9a 100644 --- a/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala-2.13+/scala/compat/java8/StreamConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala index c02ebce..ea891ab 100644 --- a/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala +++ b/src/main/scala-2.13+/scala/compat/java8/collectionImpl/package.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala index fa28114..bb49435 100644 --- a/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/Accumulates.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala index b2e7e2b..dc40b40 100644 --- a/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala index dd75253..12ac05e 100644 --- a/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala +++ b/src/main/scala-2.13+/scala/compat/java8/converterImpl/StepperExtensions.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala index 754f784..2dc27fa 100644 --- a/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala +++ b/src/main/scala-2.13+/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala b/src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala index 36838f3..b044b94 100644 --- a/src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala +++ b/src/main/scala-2.13-/scala/compat/java8/SpliteratorConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala b/src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala index 00a3d24..8d63d90 100644 --- a/src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala +++ b/src/main/scala-2.13-/scala/compat/java8/StreamConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala index 7358a1c..1950291 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Accumulator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala index 56519d2..c7e894f 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/AccumulatorLike.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala index b082769..af70491 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/DoubleAccumulator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala index 5054d26..f8599ef 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/IntAccumulator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala index b924a71..0e688bf 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/LongAccumulator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala index 8e13ea1..4bfe250 100644 --- a/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala +++ b/src/main/scala-2.13-/scala/compat/java8/collectionImpl/Stepper.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala index ff40e53..16e50bc 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/Accumulates.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala index 5b3e77f..e553443 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/AccumulatorConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala index e73e4d2..f2ec563 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/MakesSteppers.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala index e6752dc..7bab448 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala index d77daac..6c50bad 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsArray.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala index 279035b..7c3126b 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsBitSet.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala index 3ec1ae2..035aef8 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsFlatHashTable.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala index f7a9f6c..e3d053c 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsHashTable.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala index 0b7c329..352e0a2 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashMap.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala index 864a3c2..8d6cf72 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsImmHashSet.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala index b7d2fe7..f7120f6 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIndexedSeq.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala index 4343206..3f1def6 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterable.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala index 62549a1..64c2559 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsIterator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala index 27c3bff..4d6f7cc 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeGapped.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala index e7ced1a..e206228 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeImmHashMap.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala index 325b064..ce4edbe 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIndexed.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala index 518cee3..ac78af3 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeIterator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala index ed3c695..5434b0f 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeSliced.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala index 78abd12..ab2ccaa 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLikeTrieIterator.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala index d78c893..e480dab 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsLinearSeq.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala index c6e8862..cc5013e 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsMap.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala index a4c92a3..48060a7 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsRange.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala index adc78f7..b2993b2 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsString.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala index 0c9a23e..e9abb51 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsVector.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala index 04505a9..c87f798 100644 --- a/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala +++ b/src/main/scala-2.13-/scala/compat/java8/converterImpl/StepsWithTail.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala index cca7feb..206e76f 100644 --- a/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala +++ b/src/main/scala-2.13-/scala/concurrent/java8/FuturesConvertersImplCompat.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/compat/java8/DurationConverters.scala b/src/main/scala/scala/compat/java8/DurationConverters.scala index 854f9dc..55203b2 100644 --- a/src/main/scala/scala/compat/java8/DurationConverters.scala +++ b/src/main/scala/scala/compat/java8/DurationConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/compat/java8/FutureConverters.scala b/src/main/scala/scala/compat/java8/FutureConverters.scala index 7f75ee0..713d9e2 100644 --- a/src/main/scala/scala/compat/java8/FutureConverters.scala +++ b/src/main/scala/scala/compat/java8/FutureConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/compat/java8/OptionConverters.scala b/src/main/scala/scala/compat/java8/OptionConverters.scala index 64572dc..44e4194 100644 --- a/src/main/scala/scala/compat/java8/OptionConverters.scala +++ b/src/main/scala/scala/compat/java8/OptionConverters.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala index 20400b4..a032a4f 100644 --- a/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala +++ b/src/main/scala/scala/compat/java8/PrimitiveIteratorConversions.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/compat/java8/WrapperTraits.scala b/src/main/scala/scala/compat/java8/WrapperTraits.scala index 9106dfc..8d861ba 100644 --- a/src/main/scala/scala/compat/java8/WrapperTraits.scala +++ b/src/main/scala/scala/compat/java8/WrapperTraits.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). diff --git a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala index 3099d6e..9991acd 100644 --- a/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala +++ b/src/main/scala/scala/concurrent/java8/FutureConvertersImpl.scala @@ -1,7 +1,7 @@ /* * Scala (https://www.scala-lang.org) * - * Copyright EPFL and Lightbend, Inc. + * Copyright EPFL and Lightbend, Inc. dba Akka * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). From 6006bd2e18b24b45e0331a447188d4e25c8a02d0 Mon Sep 17 00:00:00 2001 From: Seth Tisue Date: Wed, 8 Jan 2025 09:47:36 -0600 Subject: [PATCH 330/340] add Scala CLA checker (#321) better late than never --- .github/workflows/cla.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/cla.yml diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 0000000..3549ded --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,11 @@ +name: "Check Scala CLA" +on: + pull_request: +jobs: + cla-check: + runs-on: ubuntu-latest + steps: + - name: Verify CLA + uses: scala/cla-checker@v1 + with: + author: ${{ github.event.pull_request.user.login }} From 2732191f9644cc6894535db5606b57db6da0aef2 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 4 Feb 2025 06:48:49 +0000 Subject: [PATCH 331/340] Update scala3-library to 3.3.5 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b7eee4c..e2a0ebf 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.15", "2.12.20", "2.11.12", "3.3.4"), + crossScalaVersions := Seq("2.13.15", "2.12.20", "2.11.12", "3.3.5"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 6870d0eadfd7f48500a712b6525311ce8a2e3aae Mon Sep 17 00:00:00 2001 From: Scala Steward <43047562+scala-steward@users.noreply.github.com> Date: Wed, 5 Mar 2025 04:15:10 +0100 Subject: [PATCH 332/340] Update scala-library to 2.13.16 (#322) --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e2a0ebf..0ea9f80 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.15", "2.12.20", "2.11.12", "3.3.5"), + crossScalaVersions := Seq("2.13.16", "2.12.20", "2.11.12", "3.3.5"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From 4f1445b8543592a155b88e505f2a29235aca631d Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Wed, 5 Mar 2025 22:44:35 +0000 Subject: [PATCH 333/340] Update sbt, scripted-plugin to 1.10.10 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 73df629..e97b272 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.7 +sbt.version=1.10.10 From 3f7ad6463c29f4378db217885cf05b377dbb5806 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 18 Mar 2025 00:14:21 +0000 Subject: [PATCH 334/340] Update sbt, scripted-plugin to 1.10.11 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index e97b272..cc68b53 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.10 +sbt.version=1.10.11 From cb4599c725d9e06c0ef7a4c266019fa0565f3629 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 9 May 2025 14:03:54 +0000 Subject: [PATCH 335/340] Update scala3-library to 3.3.6 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 0ea9f80..d6aa6cf 100644 --- a/build.sbt +++ b/build.sbt @@ -19,7 +19,7 @@ def osgiExport(scalaVersion: String, version: String) = { } lazy val commonSettings = Seq( - crossScalaVersions := Seq("2.13.16", "2.12.20", "2.11.12", "3.3.5"), + crossScalaVersions := Seq("2.13.16", "2.12.20", "2.11.12", "3.3.6"), scalaVersion := crossScalaVersions.value.head, // we could make this stricter again (BinaryAndSourceCompatible) // after our reference version was built on Scala 3.1.x From c9c402e2fd783019bc8067620289c07bfad38551 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sat, 24 May 2025 20:42:12 +0000 Subject: [PATCH 336/340] Update sbt, scripted-plugin to 1.11.0 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index cc68b53..6520f69 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.10.11 +sbt.version=1.11.0 From daa362f2bfb606256200555ab2a46b7ec2bc2586 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 3 Jun 2025 22:13:06 +0000 Subject: [PATCH 337/340] Update sbt, scripted-plugin to 1.11.1 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 6520f69..61c9b1c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.0 +sbt.version=1.11.1 From 4a5e55bad7a1ca186098927edf5508cc9a33e206 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Fri, 6 Jun 2025 06:50:06 +0000 Subject: [PATCH 338/340] Update sbt-scala-module to 3.3.0 --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 06d4e4f..983950c 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.2.2") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "3.3.0") From 94b11fbf3fa7bea2cfad3eb08b511c7ebd6b5809 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Tue, 10 Jun 2025 02:20:16 +0000 Subject: [PATCH 339/340] Update sbt, scripted-plugin to 1.11.2 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index 61c9b1c..bbb0b60 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.1 +sbt.version=1.11.2 From fabd977b403780818f3d8b856682e56938ba1875 Mon Sep 17 00:00:00 2001 From: Scala Steward Date: Sun, 6 Jul 2025 19:22:21 +0000 Subject: [PATCH 340/340] Update sbt, scripted-plugin to 1.11.3 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index bbb0b60..c02c575 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.11.2 +sbt.version=1.11.3