scala.collection.immutable.SortedMap Scala Examples

The following examples show how to use scala.collection.immutable.SortedMap. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: RadixTreeBench.scala    From radixtree   with Apache License 2.0 5 votes vote down vote up
package com.rklaehn.radixtree

import cats.kernel.Hash
import cats.kernel.instances.unit._
import ichi.bench.Thyme

import scala.collection.immutable.{HashMap, SortedMap}
import scala.io.Source
import scala.util.hashing.Hashing
import Instances._

object RadixTreeBench extends App {
  val names = Source.fromURL("http://www-01.sil.org/linguistics/wordlists/english/wordlist/wordsEn.txt").getLines.toArray
  println(names.length)
  println(names.take(10).mkString("\n"))

  implicit object EqHashing extends Hashing[Unit] {

    override def hash(x: Unit): Int = 0
  }

  lazy val th = Thyme.warmed(verbose = println, warmth = Thyme.HowWarm.BenchOff)

  val kvs = names.map(s => s -> (()))

  val kvsc = names.map(s => s.toCharArray -> (()))

  val radixTree = RadixTree(kvs: _*).packed

  val radixTreeC = RadixTree(kvsc: _*).packed

  val sortedMap = SortedMap(kvs: _*)

  val hashMap = HashMap(kvs: _*)

  def create0[K: Ordering, V](kvs: Array[(K, V)]): Int = {
    SortedMap(kvs: _*).size
  }

  def create1[K, V](kvs: Array[(K, V)])(implicit f:RadixTree.Key[K]): Int = {
    RadixTree[K,V](kvs: _*).count
  }

  def lookup0(): Boolean = {
    kvs.forall {
      case (k,v) => radixTree.contains(k)
    }
  }

  def lookup1(): Boolean = {
    kvs.forall {
      case (k,v) => hashMap.contains(k)
    }
  }

  def lookup2(): Boolean = {
    kvs.forall {
      case (k,v) => sortedMap.contains(k)
    }
  }

  def filterPrefixS(): AnyRef = {
    sortedMap.filter { case (k,v) => k.startsWith("one") }
  }

  def filterPrefixH(): AnyRef = {
    hashMap.filter { case (k,v) => k.startsWith("one") }
  }

  def filterPrefixR(): AnyRef = {
    radixTree.filterPrefix("one")
  }

  def filterContainsS(): AnyRef = {
    sortedMap.filter { case (k,v) => k.contains("one") }
  }

  def filterContainsH(): AnyRef = {
    hashMap.filter { case (k,v) => k.contains("one") }
  }

  def filterContainsR(): AnyRef = {
    radixTree.filterKeysContaining("one")
  }

  th.pbenchOffWarm("Create 1000 SortedMap vs. RadixTree")(th.Warm(create0(kvs)))(th.Warm(create1(kvs)))
  th.pbenchOffWarm("Lookup 1000 SortedMap vs. RadixTree")(th.Warm(lookup0()))(th.Warm(lookup1()))

  th.pbenchOffWarm("FilterPrefix HashMap vs. RadixTree")(th.Warm(filterPrefixH()))(th.Warm(filterPrefixR()))
  th.pbenchOffWarm("FilterPrefix SortedMap vs. RadixTree")(th.Warm(filterPrefixS()))(th.Warm(filterPrefixR()))

  th.pbenchOffWarm("FilterContains HashMap vs. RadixTree")(th.Warm(filterContainsH()))(th.Warm(filterContainsR()))
  th.pbenchOffWarm("FilterContains SortedMap vs. RadixTree")(th.Warm(filterContainsS()))(th.Warm(filterContainsR()))
} 
Example 2
Source File: Header.scala    From spark-bam   with Apache License 2.0 5 votes vote down vote up
package org.hammerlab.bam.header

import hammerlab.path._
import htsjdk.samtools.{ SAMFileHeader, SAMSequenceDictionary, SAMSequenceRecord }
import org.hammerlab.bgzf.Pos
import org.hammerlab.bgzf.block.{ UncompressedBytes, UncompressedBytesI }
import org.hammerlab.channel.ByteChannel
import org.hammerlab.genomics.reference.{ ContigName, NumLoci }

import scala.collection.JavaConverters._
import scala.collection.immutable.SortedMap

case class Header(contigLengths: ContigLengths,
                  endPos: Pos,
                  uncompressedSize: Long)

object Header {

  def apply(path: Path)(implicit cf: ContigName.Factory): Header = {
    val uncompressedBytes = UncompressedBytes(path.inputStream)
    val header = apply(uncompressedBytes)
    uncompressedBytes.close()
    header
  }

  def apply(byteStream: UncompressedBytesI[_])(implicit cf: ContigName.Factory): Header = {
    val uncompressedByteChannel: ByteChannel = byteStream
    require(
      uncompressedByteChannel.readString(4, includesNull = false) == "BAM\1"
    )

    val headerLength = uncompressedByteChannel.getInt

    
    uncompressedByteChannel.skip(headerLength)

    val numReferences = uncompressedByteChannel.getInt

    val contigLengths =
      SortedMap(
        (for {
          idx ← 0 until numReferences
        } yield {
          val refNameLen = uncompressedByteChannel.getInt
          val refName = uncompressedByteChannel.readString(refNameLen)

          idx →
            (
              refName: ContigName,
              NumLoci(uncompressedByteChannel.getInt)
            )
        }): _*
      )

    Header(
      contigLengths,
      byteStream.curPos.get,
      uncompressedByteChannel.position()
    )
  }

  implicit def toHTSJDKHeader(header: Header): SAMFileHeader =
    new SAMFileHeader(
      new SAMSequenceDictionary(
        (for {
          (name, length) ← header.contigLengths.values.toList
        } yield
          new SAMSequenceRecord(name.name, length.toInt)
        )
        .asJava
      )
    )

  import org.hammerlab.kryo._
  implicit val alsoRegister: AlsoRegister[Header] =
    AlsoRegister(
      cls[ContigLengths],
      cls[Pos]
    )
} 
Example 3
Source File: QueryExecutionSpec.scala    From neotypes   with MIT License 5 votes vote down vote up
package neotypes

import neotypes.implicits.mappers.results._
import neotypes.implicits.syntax.string._
import neotypes.internal.syntax.async._
import scala.collection.immutable.{ListMap, ListSet, SortedMap}
import scala.concurrent.Future


final class QueryExecutionSpec[F[_]](testkit: EffectTestkit[F]) extends BaseIntegrationSpec(testkit) {
  behavior of s"Excuting queries using: ${effectName}"

  it should "retrieve multiple results as a List" in executeAsFuture { s =>
    "match (p:Person) return p.name"
      .query[Int]
      .list(s)
      .map {
        names => assert(names == (0 to 10).toList)
      }
  }

  it should "retrieve multiple results as a Set" in executeAsFuture { s =>
    "match (p:Person) return p.name"
      .query[Int]
      .set(s)
      .map {
        names => assert(names == (0 to 10).toSet)
      }
  }

  it should "retrieve multiple results as a Vector" in executeAsFuture { s =>
    "match (p:Person) return p.name"
      .query[Int]
      .vector(s)
      .map {
        names => assert(names == (0 to 10).toVector)
      }
  }

  it should "retrieve multiple results as a Map" in executeAsFuture { s =>
    "match (p:Person) return p.name, 1"
      .query[(Int, Int)]
      .map(s)
      .map {
        names => assert(names == (0 to 10).map(k => k -> 1).toMap)
      }
  }

  it should "retrieve multiple results as a custom collection (ListSet)" in executeAsFuture { s =>
    "match (p:Person) return p.name"
      .query[Int]
      .collectAs(ListSet)(s)
      .map {
        names => assert(names == ListSet((0 to 10) : _*))
      }
  }

  it should "retrieve multiple results as a custom collection (ListMap)" in executeAsFuture { s =>
    "match (p:Person) return p.name, 1"
      .query[(Int, Int)]
      .collectAs(ListMap)(s)
      .map {
        names => assert(names == ListMap((0 to 10).map(k => k -> 1) : _*))
      }
  }

  it should "retrieve multiple results as a custom collection (SortedMap)" in executeAsFuture { s =>
    "match (p:Person) return p.name, 1"
      .query[(Int, Int)]
      .collectAs(SortedMap)(s)
      .map {
        names => assert(names == SortedMap((0 to 10).map(k => k -> 1) : _*))
      }
  }

  it should "retrieve a Neo4j LIST into a Scala collection (List)" in executeAsFuture { s =>
    "unwind [1, 2] as x return x"
      .query[Int]
      .list(s)
      .map {
        names => assert(names == List(1, 2))
      }
  }

  it should "retrieve a Neo4j LIST into a Scala collection (ListSet)" in executeAsFuture { s =>
    "unwind [1, 2] as x return x"
      .query[Int]
      .collectAs(ListSet)(s)
      .map {
        names => assert(names == ListSet(1, 2))
      }
  }

  override final val initQuery: String = BaseIntegrationSpec.MULTIPLE_VALUES_INIT_QUERY
} 
Example 4
Source File: SocketSession.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.server

import cats.instances.list._
import cats.syntax.traverse._
import fs2.concurrent.Topic
import polynote.buildinfo.BuildInfo
import polynote.kernel.util.Publish
import polynote.kernel.{BaseEnv, StreamThrowableOps}
import polynote.kernel.environment.{Env, PublishMessage, Config}
import polynote.kernel.interpreter.Interpreter
import polynote.kernel.logging.Logging
import polynote.messages._
import polynote.server.auth.IdentityProvider.checkPermission
import polynote.server.auth.{IdentityProvider, Permission, UserIdentity}
import uzhttp.websocket.Frame
import zio.stream.ZStream
import zio.stream.{Stream, Take}
import zio.Queue
import zio.{Promise, RIO, Task, URIO, ZIO}

import scala.collection.immutable.SortedMap

object SocketSession {

  def apply(in: Stream[Throwable, Frame], broadcastAll: Topic[Task, Option[Message]]): URIO[SessionEnv with NotebookManager, Stream[Throwable, Frame]] =
    for {
      output          <- Queue.unbounded[Take[Nothing, Message]]
      publishMessage  <- Env.add[SessionEnv with NotebookManager](Publish(output): Publish[Task, Message])
      env             <- ZIO.environment[SessionEnv with NotebookManager with PublishMessage]
      closed          <- Promise.make[Throwable, Unit]
      _               <- broadcastAll.subscribe(32).unNone.interruptAndIgnoreWhen(closed).through(publishMessage.publish).compile.drain.forkDaemon
      close            = closeQueueIf(closed, output)
    } yield parallelStreams(
        toFrames(ZStream.fromEffect(handshake) ++ Stream.fromQueue(output).unTake),
        in.handleMessages(close)(handler andThen errorHandler) ++ closeStream(closed, output),
        keepaliveStream(closed)).provide(env).catchAllCause {
      cause =>
        ZStream.empty
    }

  private val handler: Message => RIO[SessionEnv with PublishMessage with NotebookManager, Option[Message]] = {
    case ListNotebooks(_) =>
      NotebookManager.list().map {
        notebooks => Some(ListNotebooks(notebooks.map(ShortString.apply)))
      }

    case CreateNotebook(path, maybeContent) =>
      NotebookManager.assertValidPath(path) *>
        checkPermission(Permission.CreateNotebook(path)) *> NotebookManager.create(path, maybeContent).as(None)

    case RenameNotebook(path, newPath) =>
      (NotebookManager.assertValidPath(path) &> NotebookManager.assertValidPath(newPath)) *>
        checkPermission(Permission.CreateNotebook(newPath)) *> checkPermission(Permission.DeleteNotebook(path)) *>
        NotebookManager.rename(path, newPath).as(None)

    case CopyNotebook(path, newPath) =>
      (NotebookManager.assertValidPath(path) &> NotebookManager.assertValidPath(newPath)) *>
        checkPermission(Permission.CreateNotebook(newPath)) *>
        NotebookManager.copy(path, newPath).as(None)

    case DeleteNotebook(path) =>
      NotebookManager.assertValidPath(path) *>
        checkPermission(Permission.DeleteNotebook(path)) *> NotebookManager.delete(path).as(None)

    case RunningKernels(_) => for {
      paths          <- NotebookManager.listRunning()
      statuses       <- ZIO.collectAllPar(paths.map(NotebookManager.status))
      kernelStatuses  = paths.zip(statuses).map { case (p, s) => ShortString(p) -> s }
    } yield Some(RunningKernels(kernelStatuses))

    case other =>
      ZIO.succeed(None)
  }

  val errorHandler: RIO[SessionEnv with PublishMessage with NotebookManager, Option[Message]] => RIO[SessionEnv with PublishMessage with NotebookManager, Option[Message]] =
    _.catchAll {
      err => Logging.error(err).as(Some(Error(0, err)))
    }

  def handshake: RIO[SessionEnv, ServerHandshake] =
    for {
      factories <- Interpreter.Factories.access
      identity  <- UserIdentity.access
      config    <- Config.access
    } yield ServerHandshake(
      (SortedMap.empty[String, String] ++ factories.mapValues(_.head.languageName)).asInstanceOf[TinyMap[TinyString, TinyString]],
      serverVersion = BuildInfo.version,
      serverCommit = BuildInfo.commit,
      identity = identity.map(i => Identity(i.name, i.avatar.map(ShortString))),
      sparkTemplates = config.spark.flatMap(_.propertySets).getOrElse(Nil)
    )
} 
Example 5
Source File: DOperationCategoryNodeJsonProtocolSpec.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.models.json.workflow

import scala.collection.immutable.SortedMap
import scala.collection.immutable.ListMap

import org.mockito.Mockito._
import org.scalatest.mockito.MockitoSugar
import org.scalatest.{FlatSpec, Matchers}
import spray.json._
import ai.deepsense.deeplang.DOperation
import ai.deepsense.deeplang.catalogs.SortPriority
import ai.deepsense.deeplang.catalogs.doperations.{DOperationCategory, DOperationCategoryNode, DOperationDescriptor}
import ai.deepsense.models.json.workflow.DOperationCategoryNodeJsonProtocol._

object SortPriorityTest

class DOperationCategoryNodeJsonProtocolSpec extends FlatSpec with Matchers with MockitoSugar {

  "DOperationCategoryNode" should "be correctly serialized to json" in {
    val childCategory =
      new DOperationCategory(DOperationCategory.Id.randomId, "mock child name", SortPriority.coreDefault) {}
    val childNode = DOperationCategoryNode(Some(childCategory))

    val operationDescriptor = mock[DOperationDescriptor]
    when(operationDescriptor.id) thenReturn DOperation.Id.randomId
    when(operationDescriptor.name) thenReturn "mock operation descriptor name"
    when(operationDescriptor.description) thenReturn "mock operator descriptor description"

    val node = DOperationCategoryNode(
      None,
      successors = SortedMap(childCategory -> childNode),
      operations = List(operationDescriptor))

    val expectedJson = JsObject(
      "catalog" -> JsArray(
        JsObject(
          "id" -> JsString(childCategory.id.toString),
          "name" -> JsString(childCategory.name),
          "catalog" -> JsArray(),
          "items" -> JsArray())
      ),
      "items" -> JsArray(
        JsObject(
          "id" -> JsString(operationDescriptor.id.toString),
          "name" -> JsString(operationDescriptor.name),
          "description" -> JsString(operationDescriptor.description)
        )
      )
    )

    node.toJson shouldBe expectedJson
  }
} 
Example 6
Source File: CatsSuite.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.cats

import scala.collection.immutable.{ SortedMap, SortedSet }

import cats.data._
import cats.implicits._
import com.typesafe.config.ConfigFactory.parseString
import pureconfig.BaseSuite
import pureconfig.generic.auto._
import pureconfig.syntax._

class CatsSuite extends BaseSuite {

  case class Numbers(numbers: NonEmptyList[Int])
  case class NumVec(numbers: NonEmptyVector[Int])
  case class NumSet(numbers: NonEmptySet[Int])
  case class NumMap(numbers: NonEmptyMap[String, Int])
  case class NumChain(numbers: NonEmptyChain[Int])

  checkReadWrite[Numbers](parseString(s"""{ numbers: [1,2,3] }""").root() -> Numbers(NonEmptyList(1, List(2, 3))))
  checkReadWrite[NumVec](parseString(s"""{ numbers: [1,2,3] }""").root() -> NumVec(NonEmptyVector(1, Vector(2, 3))))
  checkReadWrite[NumSet](parseString(s"""{ numbers: [1,2,3] }""").root() -> NumSet(NonEmptySet(1, SortedSet(2, 3))))
  checkReadWrite[NumMap](parseString(s"""{
                                           numbers {"1": 1, "2": 2, "3": 3 }
                                         }""").root() -> NumMap(NonEmptyMap(("1", 1), SortedMap("2" -> 2, "3" -> 3))))
  checkReadWrite[NumChain](parseString(s"""{ numbers: [1,2,3] }""").root() -> NumChain(NonEmptyChain(1, 2, 3)))

  it should "return an EmptyTraversableFound when reading empty lists into NonEmptyList" in {
    val config = parseString("{ numbers: [] }")
    config.to[Numbers] should failWith(EmptyTraversableFound("scala.collection.immutable.List"), "numbers", stringConfigOrigin(1))
  }

  it should "return an EmptyTraversableFound when reading empty vector into NonEmptyVector" in {
    val config = parseString("{ numbers: [] }")
    config.to[NumVec] should failWith(EmptyTraversableFound("scala.collection.immutable.Vector"), "numbers", stringConfigOrigin(1))
  }

  it should "return an EmptyTraversableFound when reading empty set into NonEmptySet" in {
    val config = parseString("{ numbers: [] }")
    config.to[NumSet] should failWith(EmptyTraversableFound("scala.collection.immutable.SortedSet"), "numbers", stringConfigOrigin(1))
  }

  it should "return an EmptyTraversableFound when reading empty map into NonEmptyMap" in {
    val config = parseString("{ numbers{} }")
    config.to[NumMap] should failWith(EmptyTraversableFound("scala.collection.immutable.Map"), "numbers", stringConfigOrigin(1))
  }

  it should "return an EmptyTraversableFound when reading empty chain into NonEmptyChain" in {
    val config = parseString("{ numbers: [] }")
    config.to[NumChain] should failWith(EmptyTraversableFound("cats.data.Chain"), "numbers", stringConfigOrigin(1))
  }
} 
Example 7
Source File: package.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module

import _root_.cats.data._
import _root_.cats.kernel.Order
import _root_.cats.{ Alternative, Foldable }
import _root_.cats.implicits._
import pureconfig.{ ConfigReader, ConfigWriter, Exported }

import scala.collection.immutable.{ SortedMap, SortedSet }
import scala.language.higherKinds
import scala.reflect.ClassTag


package object cats {

  private[pureconfig] def fromNonEmpty[A, B](reader: ConfigReader[A])(fromX: A => Option[B])(implicit ct: ClassTag[A]): ConfigReader[B] =
    reader.emap(x => fromX(x).toRight(EmptyTraversableFound(ct.toString)))

  implicit def nonEmptyListReader[A](implicit reader: ConfigReader[List[A]]): ConfigReader[NonEmptyList[A]] =
    fromNonEmpty(reader)(NonEmptyList.fromList)
  implicit def nonEmptyListWriter[A](implicit writer: ConfigWriter[List[A]]): ConfigWriter[NonEmptyList[A]] =
    writer.contramap(_.toList)

  implicit def nonEmptyVectorReader[A](implicit reader: ConfigReader[Vector[A]]): ConfigReader[NonEmptyVector[A]] =
    fromNonEmpty(reader)(NonEmptyVector.fromVector)
  implicit def nonEmptyVectorWriter[A](implicit writer: ConfigWriter[Vector[A]]): ConfigWriter[NonEmptyVector[A]] =
    writer.contramap(_.toVector)

  implicit def nonEmptySetReader[A](implicit reader: ConfigReader[SortedSet[A]]): ConfigReader[NonEmptySet[A]] =
    fromNonEmpty(reader)(NonEmptySet.fromSet)
  implicit def nonEmptySetWriter[A](implicit writer: ConfigWriter[SortedSet[A]]): ConfigWriter[NonEmptySet[A]] =
    writer.contramap(_.toSortedSet)

  implicit def nonEmptyMapReader[A, B](implicit reader: ConfigReader[Map[A, B]], ord: Order[A]): ConfigReader[NonEmptyMap[A, B]] =
    fromNonEmpty(reader)(x => NonEmptyMap.fromMap(SortedMap(x.toSeq: _*)(ord.toOrdering)))
  implicit def nonEmptyMapWriter[A, B](implicit writer: ConfigWriter[Map[A, B]]): ConfigWriter[NonEmptyMap[A, B]] =
    writer.contramap(_.toSortedMap)

  // For emptiable foldables not covered by TraversableOnce reader/writer, e.g. Chain.
  implicit def lowPriorityNonReducibleReader[A, F[_]: Foldable: Alternative](implicit reader: ConfigReader[List[A]]): Exported[ConfigReader[F[A]]] =
    Exported(reader.map(to => (to foldRight Alternative[F].empty[A])(_.pure[F] <+> _)))
  implicit def lowPriorityNonReducibleWriter[A, F[_]: Foldable: Alternative](implicit writer: ConfigWriter[List[A]]): Exported[ConfigWriter[F[A]]] =
    Exported(writer.contramap(_.toList))

  implicit def nonEmptyChainReader[A](implicit reader: ConfigReader[Chain[A]]): ConfigReader[NonEmptyChain[A]] =
    fromNonEmpty(reader)(NonEmptyChain.fromChain)
  implicit def nonEmptyChainWriter[A](implicit writer: ConfigWriter[Chain[A]]): ConfigWriter[NonEmptyChain[A]] =
    writer.contramap(_.toChain)
} 
Example 8
Source File: RuleStatLocator.scala    From apalache   with Apache License 2.0 5 votes vote down vote up
package at.forsyte.apalache.tla.bmcmt.profiler

import java.io.{BufferedWriter, FileWriter, PrintWriter}

import scala.collection.immutable.SortedMap


class RuleStatLocator {
  private var ruleStats: Map[String, RuleStat] = Map()

  def getRuleStat(ruleName: String): RuleStat = {
    ruleStats.get(ruleName) match {
      case Some(r) => r
      case None =>
        val newRule = new RuleStat(ruleName)
        ruleStats += ruleName -> newRule
        newRule
    }
  }

  def getStats = SortedMap(ruleStats.toSeq :_*)

  def writeStats(filename: String): Unit = {
    val writer = new PrintWriter(new FileWriter(filename, false))
    writer.println("Rule profiling statistics")
    val hrule = List.fill(80)('-').mkString
    writer.println(hrule)
    writer.println("%20s %9s %9s %9s %9s %9s"
      .format("name", "calls", "cells", "smt-consts", "smt-asserts", "smt-avg-size"))
    writer.println(hrule)
    val stats = ruleStats.values.toSeq.sortWith(_.nCalls > _.nCalls)
    for (rs <- stats) {
      writer.println("%-20s %9d %9d %9d %9d %9d"
        .format(rs.ruleName, rs.nCalls, rs.nCellsSelf, rs.nSmtConstsSelf, rs.nSmtAssertsSelf, rs.smtAssertsSizeAvg))
    }
    writer.close()
  }
} 
Example 9
Source File: AnnotationParser.scala    From apalache   with Apache License 2.0 5 votes vote down vote up
package at.forsyte.apalache.tla.bmcmt.types

import at.forsyte.apalache.tla.bmcmt.RewriterException
import at.forsyte.apalache.tla.lir.convenience.tla
import at.forsyte.apalache.tla.lir.oper.{TlaFunOper, TlaSetOper}
import at.forsyte.apalache.tla.lir.values.{TlaBoolSet, TlaIntSet, TlaStrSet}
import at.forsyte.apalache.tla.lir.values.TlaStr
import at.forsyte.apalache.tla.lir.{NullEx, OperEx, TlaEx, ValEx}

import scala.collection.immutable.SortedMap


  def toTla(tp: CellT): TlaEx = {
    tp match {
      case BoolT() => ValEx(TlaBoolSet)
      case IntT() => ValEx(TlaIntSet)
      case ConstT() => ValEx(TlaStrSet)
      case FinSetT(elemT) => tla.enumSet(toTla(elemT))
      case PowSetT(domT) => tla.enumSet(toTla(domT))
      case FunT(domT, resT) => tla.funSet(toTla(domT), tla.enumSet(toTla(resT)))
      case FinFunSetT(domT, cdmType) => tla.enumSet(tla.funSet(toTla(domT), toTla(cdmType)))
      case TupleT(es) => tla.tuple(es map toTla: _*)
      case SeqT(elemT) => tla.seqSet(toTla(elemT))
      case RecordT(fields) =>
        val keys = fields.keys.toSeq
        def fieldOrVal(i: Int) = {
          val k = keys(i / 2)
          if (i % 2 == 0) tla.str(k) else toTla(fields(k))
        }
        val args = 0.until(2 * fields.size) map fieldOrVal
        OperEx(TlaFunOper.enum, args :_*)

      case _ =>
        throw new RewriterException("No translation of type %s to a TLA+ expression".format(tp), NullEx)
    }
  }
} 
Example 10
Source File: QuerySpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.rdf

import cats.kernel.Eq
import cats.syntax.show._
import ch.epfl.bluebrain.nexus.rdf.Iri._

import scala.collection.immutable.{SortedMap, SortedSet}

class QuerySpec extends RdfSpec {

  "A Query" should {
    "be constructed successfully" in {
      // format: off
      val cases = List(
        "" -> SortedMap.empty[String, SortedSet[String]],
        "a=b&a=b&a=c&a&b&b&b=c&d/&e?" -> SortedMap(
          "a" -> SortedSet("", "b", "c"),
          "b" -> SortedSet("", "c"),
          "d/" -> SortedSet(""),
          "e?" -> SortedSet("")),
        "%3D%26=%3D%26&%3D&%26" -> SortedMap(
          "=&" -> SortedSet("=&"),
          "="  -> SortedSet(""),
          "&"  -> SortedSet("")),
        "%C2%A3=%C3%86" -> SortedMap("£" -> SortedSet("Æ"))
      )
      // format: on
      forAll(cases) {
        case (raw, map) =>
          Query(raw).rightValue.value shouldEqual map
      }
    }
    "fail to parse" in {
      val cases = List("a==b", "a=b&", "a#", "a&&", "a=&b")
      forAll(cases) { str => Query(str).leftValue }
    }
    "show" in {
      val encodedDelim = urlEncode("[]#")
      Query("a=b&a=b&a=c&a&b&b&b=c&d&e" + encodedDelim).rightValue.show shouldEqual "a&a=b&a=c&b&b=c&d&e" + encodedDelim
    }
    "pct encoded representation" in {
      val utf8         = "£Æ"
      val encodedUtf8  = urlEncode(utf8)
      val allowedDelim = "!:@!$()*,"
      val encodedDelim = urlEncode("[]#")
      Query(
        utf8 + encodedUtf8 + allowedDelim + encodedDelim
      ).rightValue.pctEncoded shouldEqual (encodedUtf8 + encodedUtf8 + allowedDelim + encodedDelim)
    }
    "eq" in {
      val lhs = Query("a=b&a=b&a=c&a&b&b&b=c&d&e").rightValue
      val rhs = Query("a=b&a=b&a=c&a&b&b=c&d&e").rightValue
      Eq.eqv(lhs, rhs) shouldEqual true
    }
  }
} 
Example 11
Source File: Resolver.scala    From bazel-deps   with MIT License 5 votes vote down vote up
package com.github.johnynek.bazel_deps

import scala.collection.immutable.SortedMap
import scala.util.Try
import scala.util.control.NonFatal
import cats.MonadError
import cats.implicits._

case class ResolveFailure(message: String,
  m: MavenCoordinate,
  extension: String,
  failures: List[Exception]) extends Exception(message)

trait Resolver[F[_]] {
  implicit def resolverMonad: MonadError[F, Throwable]

  def getShas(m: List[MavenCoordinate]): F[SortedMap[MavenCoordinate, ResolvedShasValue]]

  // Build the entire transitive graph of a set of coordinates
  def buildGraph(coords: List[MavenCoordinate], m: Model): F[Graph[MavenCoordinate, Unit]]

  def run[A](fa: F[A]): Try[A]
}

trait SequentialResolver[F[_]] extends Resolver[F] {
  // This transitively adds the entire reachable graph of dep
  // to the current deps.
  def addToGraph(deps: Graph[MavenCoordinate, Unit], dep: MavenCoordinate, m: Model): F[Graph[MavenCoordinate, Unit]]

  def addAll(deps: Graph[MavenCoordinate, Unit], coords: List[MavenCoordinate], m: Model): F[Graph[MavenCoordinate, Unit]] =
    coords.foldM(deps)(addToGraph(_, _, m))

  def buildGraph(coords: List[MavenCoordinate], m: Model): F[Graph[MavenCoordinate, Unit]] =
    addAll(Graph.empty, coords, m)
} 
Example 12
Source File: PhaseRes.scala    From Converter   with GNU General Public License v3.0 5 votes vote down vote up
package org.scalablytyped.converter.internal.phases

import java.nio.channels.{ClosedByInterruptException, FileLockInterruptionException}

import com.olvind.logging.Logger
import com.olvind.logging.Logger.LoggedException

import scala.collection.immutable.{SortedMap, TreeMap}
import scala.concurrent.ExecutionException
import scala.util.control.NonFatal

sealed trait PhaseRes[Id, T] extends Product with Serializable {
  import PhaseRes._

  def foreach(f: T => Unit): PhaseRes[Id, Unit] = map(f)

  def map[U](f: T => U): PhaseRes[Id, U] =
    this match {
      case Ok(value)       => Ok(f(value))
      case Ignore()        => Ignore()
      case Failure(errors) => Failure(errors)
    }

  def flatMap[U](f: T => PhaseRes[Id, U]): PhaseRes[Id, U] =
    this match {
      case Ok(value)       => f(value)
      case Ignore()        => Ignore()
      case Failure(errors) => Failure(errors)
    }
}

object PhaseRes {
  final case class Ok[Id, T](value: T) extends PhaseRes[Id, T]
  final case class Ignore[Id, T]() extends PhaseRes[Id, T]
  final case class Failure[Id, T](errors: Map[Id, Either[Throwable, String]]) extends PhaseRes[Id, T]

  def fromEither[Id, L, R](id: Id, e: Either[String, R]): PhaseRes[Id, R] =
    e match {
      case Right(value) => Ok(value)
      case Left(error)  => Failure(Map(id -> Right(error)))
    }

  def fromOption[Id, T](id: Id, e: Option[T], onEmpty: => Either[Throwable, String]): PhaseRes[Id, T] =
    e match {
      case Some(value) => Ok(value)
      case None        => Failure(Map(id -> onEmpty))
    }

  def sequenceSet[Id, T](rs: Set[PhaseRes[Id, T]]): PhaseRes[Id, Set[T]] =
    rs.foldLeft[PhaseRes[Id, Set[T]]](Ok(Set.empty)) {
      case (other, Ignore())                 => other
      case (Ok(ts), Ok(t))                   => Ok(ts + t)
      case (Ok(_), Failure(errors))          => Failure(errors)
      case (Failure(errors), Failure(error)) => Failure(errors ++ error)
      case (error @ Failure(_), Ok(_))       => error
      case (Ignore(), Ok(t))                 => Ok(Set(t))
      case (Ignore(), Failure(error))        => Failure(error)
    }

  def sequenceMap[Id: Ordering, T](rs: SortedMap[Id, PhaseRes[Id, T]]): PhaseRes[Id, SortedMap[Id, T]] =
    rs.foldLeft[PhaseRes[Id, SortedMap[Id, T]]](Ok(TreeMap.empty[Id, T])) {
      case (other, (_, Ignore()))                    => other
      case (Ok(map), (id, Ok(value)))                => Ok(map + ((id, value)))
      case (Ok(_), (_, Failure(errors)))             => Failure(errors)
      case (Failure(errors1), (_, Failure(errors2))) => Failure(errors1 ++ errors2)
      case (error @ Failure(_), _)                   => error
      case (Ignore(), (id, Ok(value)))               => Ok(TreeMap((id, value)))
      case (Ignore(), (_, Failure(errors)))          => Failure(errors)
    }

  def attempt[Id, T](id: Id, logger: Logger[Unit], t: => PhaseRes[Id, T]): PhaseRes[Id, T] =
    try t
    catch {
      case x: InterruptedException => throw x
      case x: ClosedByInterruptException => throw x
      case x: FileLockInterruptionException => throw x
      case x: ExecutionException if x.getCause != null =>
        val th = x.getCause
        logger.error(s"Caught exception: ${th.getMessage}", th)
        Failure[Id, T](Map(id -> Left(th)))
      case th: LoggedException =>
        Failure[Id, T](Map(id -> Left(th)))
      case NonFatal(th) =>
        logger.error(s"Caught exception: ${th.getMessage}", th)
        Failure[Id, T](Map(id -> Left(th)))
      case th: StackOverflowError =>
        logger.error("StackOverflowError", th)
        Failure[Id, T](Map(id -> Left(th)))
    }
} 
Example 13
Source File: Memoize.scala    From bosatsu   with Apache License 2.0 5 votes vote down vote up
package org.bykn.bosatsu.graph

import java.util.concurrent.ConcurrentHashMap
import org.bykn.bosatsu.Par
import scala.collection.immutable.SortedMap

object Memoize {

  
  def memoizeDagFuture[A, B](fn: (A, A => Par.F[B]) => Par.F[B]): A => Par.F[B] = {
    val cache: ConcurrentHashMap[A, Par.P[B]] = new ConcurrentHashMap[A, Par.P[B]]()

    new Function[A, Par.F[B]] { self =>
      def apply(a: A) = {
        val prom = Par.promise[B]
        val prevProm = cache.putIfAbsent(a, prom)
        if (prevProm eq null) {
          // no one was running this job, we have to
          val resFut = fn(a, self)
          Par.complete(prom, resFut)
          resFut
        }
        else {
          // someone else is already working:
          Par.toF(prevProm)
        }
      }
    }
  }
} 
Example 14
Source File: DefinedType.scala    From bosatsu   with Apache License 2.0 5 votes vote down vote up
package org.bykn.bosatsu.rankn

import cats.{Applicative, Eval, Traverse}
import org.bykn.bosatsu.{TypeName, PackageName}
import scala.collection.immutable.SortedMap

import cats.implicits._

final case class DefinedType[+A](
  packageName: PackageName,
  name: TypeName,
  annotatedTypeParams: List[(Type.Var.Bound, A)],
  constructors: List[ConstructorFn]) {

  val typeParams: List[Type.Var.Bound] =
    annotatedTypeParams.map(_._1)

  require(typeParams.distinct == typeParams, typeParams.toString)

  
  val natLike: DefinedType.NatLike =
    constructors match {
      case c0 :: c1 :: Nil =>
        // exactly two constructor functions
        if (c0.isZeroArg && c1.hasSingleArgType(toTypeTyConst)) DefinedType.NatLike.ZeroFirst
        else if (c1.isZeroArg && c0.hasSingleArgType(toTypeTyConst)) DefinedType.NatLike.ZeroLast
        else DefinedType.NatLike.Not
      case _ => DefinedType.NatLike.Not
    }
}

object DefinedType {
  sealed abstract class NatLike
  object NatLike {
    final case object Not extends NatLike
    final case class Is(val zeroFirst: Boolean) extends NatLike {
      @inline def zeroLast: Boolean = !zeroFirst
      def idxIsZero(idx: Int): Boolean =
        (zeroFirst && (idx == 0)) || (zeroLast && (idx == 1))
    }
    val ZeroFirst: Is = Is(true)
    val ZeroLast: Is = Is(false)
  }

  def toTypeConst(pn: PackageName, nm: TypeName): Type.Const.Defined =
    Type.Const.Defined(pn, nm)

  def listToMap[A](dts: List[DefinedType[A]]): SortedMap[(PackageName, TypeName), DefinedType[A]] =
    SortedMap(dts.map { dt => (dt.packageName, dt.name) -> dt }: _*)

  implicit val definedTypeTraverse: Traverse[DefinedType] =
    new Traverse[DefinedType] {
      val listTup = Traverse[List].compose[(Type.Var.Bound, ?)]
      def traverse[F[_]: Applicative, A, B](da: DefinedType[A])(fn: A => F[B]): F[DefinedType[B]] =
        listTup.traverse(da.annotatedTypeParams)(fn).map { ap =>
          da.copy(annotatedTypeParams = ap)
        }

      def foldRight[A, B](fa: DefinedType[A], b: Eval[B])(fn: (A, Eval[B]) => Eval[B]): Eval[B] =
        listTup.foldRight(fa.annotatedTypeParams, b)(fn)

      def foldLeft[A, B](fa: DefinedType[A], b: B)(fn: (B, A) => B): B =
        listTup.foldLeft(fa.annotatedTypeParams, b)(fn)

      override def map[A, B](fa: DefinedType[A])(fn: A => B): DefinedType[B] =
        fa.copy(annotatedTypeParams = listTup.map(fa.annotatedTypeParams)(fn))
    }
} 
Example 15
Source File: TypeEnv.scala    From bosatsu   with Apache License 2.0 5 votes vote down vote up
package org.bykn.bosatsu.rankn

import org.bykn.bosatsu.{TypeName, PackageName}
import scala.collection.immutable.SortedMap

import org.bykn.bosatsu.Identifier
import org.bykn.bosatsu.Identifier.{Bindable, Constructor}

class TypeEnv[+A] private (
  protected val values: SortedMap[(PackageName, Identifier), Type],
  protected val constructors: SortedMap[(PackageName, Constructor), (List[(Bindable, Type)], DefinedType[A], Type)],
  val definedTypes: SortedMap[(PackageName, TypeName), DefinedType[A]]) {

  override def equals(that: Any): Boolean =
    that match {
      case te: TypeEnv[_] =>
        (values == te.values) &&
        (constructors == te.constructors) &&
        (definedTypes == te.definedTypes)
      case _ => false
    }

  lazy val referencedPackages: Set[PackageName] = {
    def keys1[K, B](k: SortedMap[(PackageName, K), B]): Iterator[PackageName] =
      k.keys.iterator.map(_._1)

    (keys1(values) ++ keys1(constructors) ++ keys1(definedTypes)).toSet
  }

  override def hashCode: Int = {
    (getClass, values, constructors, definedTypes).hashCode
  }

  override def toString: String =
    s"TypeEnv($values, $constructors, $definedTypes)"

  def allDefinedTypes: List[DefinedType[A]] =
    definedTypes.values.toList.sortBy { dt => (dt.packageName, dt.name) }

  def getConstructor(p: PackageName, c: Constructor): Option[(List[(Bindable, Type)], DefinedType[A], Type)] =
    constructors.get((p, c))

  def getType(p: PackageName, t: TypeName): Option[DefinedType[A]] =
    definedTypes.get((p, t))

  def getValue(p: PackageName, n: Identifier): Option[Type] =
    values.get((p, n))

  def localValuesOf(p: PackageName): SortedMap[Identifier, Type] =
    (SortedMap.newBuilder[Identifier, Type] ++= values.iterator.collect { case ((pn, n), v) if pn == p => (n, v) }).result

  def addConstructor[A1 >: A](pack: PackageName,
    dt: DefinedType[A1],
    cf: ConstructorFn): TypeEnv[A1] = {
      val nec = constructors.updated((pack, cf.name), (cf.args, dt, cf.fnType))
      // add this constructor to the values
      val v1 = values.updated((pack, cf.name), cf.fnType)
      new TypeEnv(values = v1, constructors = nec, definedTypes = definedTypes)
    }

  
  def fromDefinitions[A](defs: List[DefinedType[A]]): TypeEnv[A] =
    defs.foldLeft(empty: TypeEnv[A])(_.addDefinedTypeAndConstructors(_))

  def fromParsed[A](p: ParsedTypeEnv[A]): TypeEnv[A] = {
    val t1 = p.allDefinedTypes.foldLeft(empty: TypeEnv[A])(_.addDefinedTypeAndConstructors(_))
    p.externalDefs.foldLeft(t1) { case (t1, (p, n, t)) => t1.addExternalValue(p, n, t) }
  }
} 
Example 16
Source File: TopicCommit.scala    From kafka-journal   with MIT License 5 votes vote down vote up
package com.evolutiongaming.kafka.journal.replicator

import java.time.Instant

import cats.Applicative
import cats.data.{NonEmptyMap => Nem}
import cats.effect.concurrent.Ref
import cats.effect.{Clock, Sync}
import cats.implicits._
import com.evolutiongaming.catshelper.ClockHelper._
import com.evolutiongaming.catshelper.DataHelper._
import com.evolutiongaming.kafka.journal.util.TemporalHelper._
import com.evolutiongaming.kafka.journal.KafkaConsumer
import com.evolutiongaming.skafka._

import scala.collection.immutable.SortedMap
import scala.concurrent.duration._

trait TopicCommit[F[_]] {

  def apply(offsets: Nem[Partition, Offset]): F[Unit]
}

object TopicCommit {

  def empty[F[_] : Applicative]: TopicCommit[F] = (_: Nem[Partition, Offset]) => ().pure[F]

  def apply[F[_]](
    topic: Topic,
    metadata: String,
    consumer: KafkaConsumer[F, _, _],
  ): TopicCommit[F] = {
    offsets: Nem[Partition, Offset] => {
      val offsets1 = offsets.mapKV { (partition, offset) =>
        val offset1 = OffsetAndMetadata(offset, metadata)
        val partition1 = TopicPartition(topic, partition)
        (partition1, offset1)
      }
      consumer.commit(offsets1)
    }
  }

  def delayed[F[_] : Sync : Clock](
    delay: FiniteDuration,
    commit: TopicCommit[F]
  ): F[TopicCommit[F]] = {

    case class State(until: Instant, offsets: SortedMap[Partition, Offset] = SortedMap.empty)

    for {
      timestamp <- Clock[F].instant
      stateRef  <- Ref[F].of(State(timestamp + delay))
    } yield {
      new TopicCommit[F] {
        def apply(offsets: Nem[Partition, Offset]) = {

          def apply(state: State, timestamp: Instant) = {
            val offsets1 = state.offsets ++ offsets.toSortedMap
            if (state.until <= timestamp) {
              offsets1
                .toNem
                .foldMapM { offsets => commit(offsets) }
                .as(State(timestamp + delay))
            } else {
              state
                .copy(offsets = offsets1)
                .pure[F]
            }
          }

          for {
            timestamp <- Clock[F].instant
            state     <- stateRef.get
            state     <- apply(state, timestamp)
            _         <- stateRef.set(state)
          } yield {}
        }
      }
    }
  }
} 
Example 17
Source File: QueriesService.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package cqrs.queries

import java.util.UUID

import akka.actor.Scheduler
import play.api.libs.ws.WSClient

import scala.concurrent.ExecutionContext.Implicits.global
import cqrs.commands.{CommandsEndpoints, MeterCreated, RecordAdded, StoredEvent}

import scala.collection.immutable.SortedMap
import scala.concurrent.duration.DurationInt
import scala.concurrent.Future
import scala.concurrent.stm.{Ref, atomic}


  private def applyEvent(state: State, storedEvent: StoredEvent): State =
    storedEvent match {
      case StoredEvent(t, MeterCreated(id, label)) =>
        state.copy(
          lastEventTimestamp = Some(t),
          meters = state.meters + (id -> Meter(id, label, SortedMap.empty))
        )
      case StoredEvent(t, RecordAdded(id, date, value)) =>
        val meter = state.meters(id)
        val updatedMeter =
          meter.copy(timeSeries = meter.timeSeries + (date -> value))
        state.copy(
          lastEventTimestamp = Some(t),
          meters = state.meters + (id -> updatedMeter)
        )
    }

} 
Example 18
Source File: Histogram.scala    From spark-util   with Apache License 2.0 5 votes vote down vote up
package org.hammerlab.spark.accumulator

import org.apache.spark.SparkContext
import org.apache.spark.util.AccumulatorV2

import scala.collection.immutable.SortedMap
import scala.collection.mutable


case class Histogram[T: Ordering](var map: mutable.Map[T, Long] = mutable.Map.empty[T, Long])
  extends AccumulatorV2[T, SortedMap[T, Long]] {

  override def isZero: Boolean = map.isEmpty

  override def copy(): AccumulatorV2[T, SortedMap[T, Long]] =
    Histogram(map.clone())

  override def reset(): Unit = map = mutable.Map.empty[T, Long]

  override def add(k: T): Unit =
    map.update(
      k,
      map.getOrElse(k, 0L) + 1
    )

  override def merge(other: AccumulatorV2[T, SortedMap[T, Long]]): Unit =
    for {
      (k, v) ← other.value
    } {
      map.update(k, map.getOrElse(k, 0L) + v)
    }

  override def value: SortedMap[T, Long] = SortedMap(map.toSeq: _*)
}

object Histogram {
  def apply[T: Ordering](name: String)(implicit sc: SparkContext): Histogram[T] = {
    val a = Histogram[T]()
    sc.register(a, name)
    a
  }
} 
Example 19
Source File: SbtProject.scala    From Converter   with GNU General Public License v3.0 5 votes vote down vote up
package org.scalablytyped.converter.internal
package importer
package build

import org.scalablytyped.converter.internal.importer.documentation.Npmjs
import org.scalablytyped.converter.internal.maps.MapOps
import org.scalablytyped.converter.internal.scalajs.Dep

import scala.collection.immutable.SortedMap
import scala.collection.mutable

case class SbtProject(name: String, artifactId: String, reference: Dep.ScalaJs)(
    val baseDir:            os.Path,
    val deps:               Map[Source, PublishedSbtProject],
    val metadata:           Option[Npmjs.Data],
)

case class PublishedSbtProject(project: SbtProject)(
    val classfileDir:                   os.Path,
    val localIvyFiles:                  IvyLayout[os.Path, _],
    val publishedOpt:                   Option[Unit],
)

object PublishedSbtProject {
  object Unpack {
    def unapply(_m: SortedMap[Source, PublishedSbtProject]): Some[SortedMap[Source, PublishedSbtProject]] =
      Some(apply(_m))

    def apply(_m: SortedMap[Source, PublishedSbtProject]): SortedMap[Source, PublishedSbtProject] = {
      val ret = mutable.HashMap.empty[Source, PublishedSbtProject]

      def go(libs: mutable.Map[Source, PublishedSbtProject], ds: Map[Source, PublishedSbtProject]): Unit =
        ds foreach {
          case (s, lib) =>
            if (!libs.contains(s)) {
              libs(s) = lib
              go(libs, lib.project.deps)
            }
        }

      go(ret, _m)
      ret.toSorted
    }
  }
} 
Example 20
Source File: LibScalaJs.scala    From Converter   with GNU General Public License v3.0 5 votes vote down vote up
package org.scalablytyped.converter.internal
package importer

import org.scalablytyped.converter.internal.importer.Source.TsLibSource
import org.scalablytyped.converter.internal.maps.MapOps
import org.scalablytyped.converter.internal.scalajs.{Name, PackageTree, TreeScope}

import scala.collection.immutable.SortedMap
import scala.collection.mutable

case class LibScalaJs(source: TsLibSource)(
    val libName:              String,
    val scalaName:            Name,
    val libVersion:           LibraryVersion,
    val packageTree:          PackageTree,
    val dependencies:         Map[TsLibSource, LibScalaJs],
    val isStdLib:             Boolean,
    val names:                AdaptiveNamingImport,
) extends TreeScope.Lib

object LibScalaJs {

  object Unpack {
    def unapply(_m: SortedMap[Source, LibScalaJs]): Some[SortedMap[TsLibSource, LibScalaJs]] =
      Some(apply(_m))

    def apply(_m: SortedMap[Source, LibScalaJs]): SortedMap[TsLibSource, LibScalaJs] = {

      val libs = mutable.HashMap.empty[TsLibSource, LibScalaJs]

      def go(m: Map[Source, LibScalaJs]): Unit =
        m foreach {
          case (s: TsLibSource, lib: LibScalaJs) =>
            if (!libs.contains(s)) {
              libs(s) = lib
              goLibs(libs, lib.dependencies)
            }

          case other => sys.error(s"Unexpected $other")
        }

      go(_m)

      libs.toSorted
    }

    def goLibs(libs: mutable.Map[TsLibSource, LibScalaJs], ds: Map[TsLibSource, LibScalaJs]): Unit =
      ds foreach {
        case (s, lib) =>
          if (!libs.contains(s)) {
            libs(s) = lib
            goLibs(libs, lib.dependencies)
          }
      }
  }
} 
Example 21
Source File: Phase1Res.scala    From Converter   with GNU General Public License v3.0 5 votes vote down vote up
package org.scalablytyped.converter.internal
package importer

import org.scalablytyped.converter.internal.importer.Source.{TsHelperFile, TsLibSource}
import org.scalablytyped.converter.internal.maps.MapOps
import org.scalablytyped.converter.internal.ts.{TsIdentLibrary, TsParsedFile}

import scala.collection.immutable.SortedMap
import scala.collection.mutable

sealed trait Phase1Res


object Phase1Res {

  final case class LibTs(source: TsLibSource)(
      val version:               LibraryVersion,
      val parsed:                TsParsedFile,
      val dependencies:          SortedMap[TsLibSource, LibTs],
  ) extends Phase1Res {
    def name: TsIdentLibrary = source.libName
  }

  case class LibraryPart(file: FileAndInlinesRec, deps: SortedMap[Source, Phase1Res]) extends Phase1Res

  case class FileAndInlinesRec(file: TsParsedFile, toInline: SortedMap[Source, LibraryPart])

  case class FileAndInlinesFlat(file: TsParsedFile, toInline: SortedMap[Source, TsParsedFile])

  object UnpackLibs {
    def unapply(_m: Map[TsLibSource, LibTs]): Some[Map[TsLibSource, LibTs]] =
      Some(apply(_m))

    def apply(_m: Map[TsLibSource, LibTs]): Map[TsLibSource, LibTs] = {
      val libs = mutable.HashMap.empty[TsLibSource, LibTs]
      Unpack.goLibs(libs, _m)
      libs.toMap
    }
  }

  object Unpack {
    def unapply(
        _m: SortedMap[Source, Phase1Res],
    ): Some[(SortedMap[TsHelperFile, FileAndInlinesFlat], SortedMap[TsLibSource, LibTs])] =
      Some(apply(_m))

    def apply(
        _m: SortedMap[Source, Phase1Res],
    ): (SortedMap[TsHelperFile, FileAndInlinesFlat], SortedMap[TsLibSource, LibTs]) = {

      val libParts = mutable.HashMap.empty[TsHelperFile, FileAndInlinesFlat]
      val libs     = mutable.HashMap.empty[TsLibSource, LibTs]

      def go(m: Map[Source, Phase1Res]): Unit =
        m foreach {
          case (s: TsHelperFile, libPart: LibraryPart) =>
            if (!libParts.contains(s)) {
              def flatten(os: Option[Source], _f: FileAndInlinesRec): SortedMap[Source, TsParsedFile] = {
                val first: SortedMap[Source, TsParsedFile] =
                  os match {
                    case None     => SortedMap.empty
                    case Some(s2) => SortedMap(s2 -> _f.file)
                  }
                val rest: SortedMap[Source, TsParsedFile] =
                  _f.toInline.flatMap {
                    case (s2, x: LibraryPart) =>
                      go(x.deps)
                      flatten(Some(s2), x.file)
                  }
                first ++ rest
              }

              libParts(s) = FileAndInlinesFlat(libPart.file.file, flatten(None, libPart.file))
              go(libPart.deps)
            }
          case (s: TsLibSource, lib: LibTs) =>
            if (!libs.contains(s)) {
              libs(s) = lib
              goLibs(libs, lib.dependencies)
            }

          case other => sys.error(s"Unexpected $other")
        }

      go(_m)

      (libParts.toSorted, libs.toSorted)
    }

    def goLibs(libs: mutable.Map[TsLibSource, LibTs], ds: Map[TsLibSource, LibTs]): Unit =
      ds foreach {
        case (s, lib) =>
          if (!libs.contains(s)) {
            libs(s) = lib
            goLibs(libs, lib.dependencies)
          }
      }
  }
}