src/Pure/General/linear_set.scala
author wenzelm
Tue, 01 Sep 2009 13:31:22 +0200
changeset 32465 87f0e1b2d3f2
parent 32464 5b9731f83569
child 32576 20b261654e33
permissions -rw-r--r--
misc cleanup and internal reorganization;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/General/linear_set.scala
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
     3
    Author:     Fabian Immler TU Munich
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     4
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     5
Sets with canonical linear order, or immutable linked-lists.
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     6
*/
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     7
package isabelle
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     8
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     9
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    10
object Linear_Set
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    11
{
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    12
  private case class Rep[A](
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    13
    val first_elem: Option[A], val last_elem: Option[A], val body: Map[A, A])
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    14
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    15
  private def empty_rep[A] = Rep[A](None, None, Map())
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    16
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    17
  private def make[A](first_elem: Option[A], last_elem: Option[A], body: Map[A, A]): Linear_Set[A] =
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    18
    new Linear_Set[A] { override val rep = Rep(first_elem, last_elem, body) }
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    19
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    20
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    21
  def empty[A]: Linear_Set[A] = new Linear_Set
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    22
  def apply[A](elems: A*): Linear_Set[A] = empty[A] ++ elems
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    23
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    24
  class Duplicate(s: String) extends Exception(s)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    25
  class Undefined(s: String) extends Exception(s)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    26
}
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    27
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    28
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    29
class Linear_Set[A] extends scala.collection.immutable.Set[A]
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    30
{
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    31
  /* representation */
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    32
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    33
  protected val rep = Linear_Set.empty_rep[A]
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    34
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    35
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    36
  /* auxiliary operations */
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    37
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    38
  def next(elem: A) = rep.body.get(elem)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    39
  def prev(elem: A) = rep.body.find(_._2 == elem).map(_._1)   // slow
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    40
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    41
  private def _insert_after(hook: Option[A], elem: A): Linear_Set[A] =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    42
    if (contains(elem)) throw new Linear_Set.Duplicate(elem.toString)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    43
    else hook match {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    44
      case Some(hook) =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    45
        if (!contains(hook)) throw new Linear_Set.Undefined(hook.toString)
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    46
        else if (rep.body.isDefinedAt(hook))
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    47
          Linear_Set.make(rep.first_elem, rep.last_elem,
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    48
            rep.body - hook + (hook -> elem) + (elem -> rep.body(hook)))
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    49
        else Linear_Set.make(rep.first_elem, Some(elem), rep.body + (hook -> elem))
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    50
      case None =>
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    51
        if (isEmpty) Linear_Set.make(Some(elem), Some(elem), Map())
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    52
        else Linear_Set.make(Some(elem), rep.last_elem, rep.body + (elem -> rep.first_elem.get))
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    53
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    54
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    55
  def insert_after(hook: Option[A], elems: Seq[A]): Linear_Set[A] =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    56
    elems.reverse.foldLeft (this) ((ls, elem) => ls._insert_after(hook, elem))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    57
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    58
  def delete_after(elem: Option[A]): Linear_Set[A] =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    59
    elem match {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    60
      case Some(elem) =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    61
        if (!contains(elem)) throw new Linear_Set.Undefined(elem.toString)
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    62
        else if (!rep.body.isDefinedAt(elem)) throw new Linear_Set.Undefined(null)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    63
        else if (rep.body(elem) == rep.last_elem.get)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    64
          Linear_Set.make(rep.first_elem, Some(elem), rep.body - elem)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    65
        else Linear_Set.make(rep.first_elem, rep.last_elem,
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    66
          rep.body - elem - rep.body(elem) + (elem -> rep.body(rep.body(elem))))
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    67
      case None =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    68
        if (isEmpty) throw new Linear_Set.Undefined(null)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    69
        else if (size == 1) empty
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    70
        else Linear_Set.make(Some(rep.body(rep.first_elem.get)), rep.last_elem, rep.body - rep.first_elem.get)
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    71
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    72
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    73
  def delete_between(from: Option[A], to: Option[A]): Linear_Set[A] = {
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    74
    if(!rep.first_elem.isDefined) this
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    75
    else {
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    76
      val next =
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    77
        if (from == rep.last_elem) None
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    78
        else if (from == None) rep.first_elem
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    79
        else from.map(rep.body(_))
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    80
      if (next == to) this
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    81
      else delete_after(from).delete_between(from, to)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    82
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    83
  }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    84
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    85
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    86
  /* Set methods */
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    87
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    88
  override def stringPrefix = "Linear_Set"
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    89
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    90
  def empty[B]: Linear_Set[B] = Linear_Set.empty
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    91
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    92
  override def isEmpty: Boolean = !rep.last_elem.isDefined
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    93
  def size: Int = if (isEmpty) 0 else rep.body.size + 1
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    94
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    95
  def elements = new Iterator[A] {
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
    96
    private var next_elem = rep.first_elem
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    97
    def hasNext = next_elem.isDefined
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    98
    def next = {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    99
      val elem = next_elem.get
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   100
      next_elem = if (rep.body.isDefinedAt(elem)) Some(rep.body(elem)) else None
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   101
      elem
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   102
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   103
  }
32465
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   104
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   105
  def contains(elem: A): Boolean =
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   106
    !isEmpty && (rep.last_elem.get == elem || rep.body.isDefinedAt(elem))
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   107
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   108
  def + (elem: A): Linear_Set[A] = _insert_after(rep.last_elem, elem)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   109
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   110
  override def + (elem1: A, elem2: A, elems: A*): Linear_Set[A] =
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   111
    this + elem1 + elem2 ++ elems
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   112
  override def ++ (elems: Iterable[A]): Linear_Set[A] = (this /: elems) ((s, elem) => s + elem)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   113
  override def ++ (elems: Iterator[A]): Linear_Set[A] = (this /: elems) ((s, elem) => s + elem)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   114
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   115
  def - (elem: A): Linear_Set[A] =
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   116
    if (!contains(elem)) throw new Linear_Set.Undefined(elem.toString)
87f0e1b2d3f2 misc cleanup and internal reorganization;
wenzelm
parents: 32464
diff changeset
   117
    else delete_after(prev(elem))
32464
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   118
}