src/Pure/General/multi_map.scala
author wenzelm
Fri, 01 Apr 2022 17:06:10 +0200
changeset 75393 87ebf5a50283
parent 73362 dde25151c3c1
permissions -rw-r--r--
clarified formatting, for the sake of scala3;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/General/multi_map.scala
56744
0b74d1df4b8e tuned headers;
wenzelm
parents: 55618
diff changeset
     2
    Author:     Makarius
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     3
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     4
Maps with multiple entries per key.
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     5
*/
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     6
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     7
package isabelle
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
     8
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
     9
import scala.collection.mutable
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    10
import scala.collection.{IterableFactory, MapFactory, MapFactoryDefaults}
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    11
import scala.collection.immutable.{Iterable, MapOps}
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    12
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    13
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73362
diff changeset
    14
object Multi_Map extends MapFactory[Multi_Map] {
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    15
  private val empty_val: Multi_Map[Any, Nothing] = new Multi_Map[Any, Nothing](Map.empty)
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    16
  def empty[A, B]: Multi_Map[A, B] = empty_val.asInstanceOf[Multi_Map[A, B]]
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    17
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    18
  def from[A, B](entries: IterableOnce[(A, B)]): Multi_Map[A, B] =
73362
dde25151c3c1 tuned --- fewer warnings;
wenzelm
parents: 73360
diff changeset
    19
    entries.iterator.foldLeft(empty[A, B]) { case (m, (a, b)) => m.insert(a, b) }
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    20
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    21
  override def newBuilder[A, B]: mutable.Builder[(A, B), Multi_Map[A, B]] = new Builder[A, B]
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73362
diff changeset
    22
  private class Builder[A, B] extends mutable.Builder[(A, B), Multi_Map[A, B]] {
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    23
    private var res = empty[A, B]
73340
0ffcad1f6130 tuned --- fewer warnings;
wenzelm
parents: 73136
diff changeset
    24
    override def clear(): Unit = { res = empty[A, B] }
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    25
    override def addOne(p: (A, B)): this.type = { res = res.insert(p._1, p._2); this }
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    26
    override def result(): Multi_Map[A, B] = res
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    27
  }
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    28
}
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    29
59073
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    30
final class Multi_Map[A, +B] private(protected val rep: Map[A, List[B]])
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    31
  extends Iterable[(A, B)]
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    32
    with MapOps[A, B, Multi_Map, Multi_Map[A, B]]
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73362
diff changeset
    33
    with MapFactoryDefaults[A, B, Multi_Map, Iterable] {
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    34
  /* Multi_Map operations */
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    35
55488
60c159d490a2 more integrity checks of theory names vs. full node names;
wenzelm
parents: 52975
diff changeset
    36
  def iterator_list: Iterator[(A, List[B])] = rep.iterator
60c159d490a2 more integrity checks of theory names vs. full node names;
wenzelm
parents: 52975
diff changeset
    37
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    38
  def get_list(a: A): List[B] = rep.getOrElse(a, Nil)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    39
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73362
diff changeset
    40
  def insert[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = {
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    41
    val bs = get_list(a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    42
    if (bs.contains(b)) this
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    43
    else new Multi_Map(rep + (a -> (b :: bs)))
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    44
  }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    45
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 73362
diff changeset
    46
  def remove[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = {
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    47
    val bs = get_list(a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    48
    if (bs.contains(b)) {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    49
      bs.filterNot(_ == b) match {
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    50
        case Nil => new Multi_Map(rep - a)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    51
        case bs1 => new Multi_Map(rep + (a -> bs1))
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    52
      }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    53
    }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    54
    else this
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    55
  }
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    56
59073
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    57
  def ++[B1 >: B] (other: Multi_Map[A, B1]): Multi_Map[A, B1] =
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    58
    if (this eq other) this
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    59
    else if (isEmpty) other
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    60
    else
73359
d8a0e996614b tuned --- fewer warnings;
wenzelm
parents: 73340
diff changeset
    61
      other.rep.iterator.foldLeft(this.asInstanceOf[Multi_Map[A, B1]]) {
73360
4123fca23296 tuned --- fewer warnings;
wenzelm
parents: 73359
diff changeset
    62
        case (m1, (a, bs)) => bs.foldRight(m1) { case (b, m2) => m2.insert(a, b) }
59073
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    63
      }
dcecfcc56dce more merge operations;
wenzelm
parents: 56744
diff changeset
    64
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    65
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    66
  /* Map operations */
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    67
71601
97ccf48c2f0c misc tuning based on hints by IntelliJ IDEA;
wenzelm
parents: 64370
diff changeset
    68
  override def empty: Multi_Map[A, Nothing] = Multi_Map.empty
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    69
  override def isEmpty: Boolean = rep.isEmpty
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    70
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    71
  override def keySet: Set[A] = rep.keySet
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    72
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    73
  override def iterator: Iterator[(A, B)] =
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    74
    for ((a, bs) <- rep.iterator; b <- bs.iterator) yield (a, b)
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    75
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    76
  def get(a: A): Option[B] = get_list(a).headOption
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    77
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    78
  override def updated[B1 >: B](a: A, b: B1): Multi_Map[A, B1] = insert(a, b)
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    79
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    80
  override def removed(a: A): Multi_Map[A, B] =
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    81
    if (rep.isDefinedAt(a)) new Multi_Map(rep - a) else this
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    82
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    83
  override def mapFactory: MapFactory[Multi_Map] = Multi_Map
63579
73939a9b70a3 support 'abbrevs' within theory header;
wenzelm
parents: 59073
diff changeset
    84
73136
ca17e9ebfdf1 updated to scala-2.13.4;
wenzelm
parents: 71601
diff changeset
    85
  override def toString: String = mkString("Multi_Map(", ", ", ")")
52975
457c006f91bb support for maps with multiple entries per key;
wenzelm
parents:
diff changeset
    86
}