src/Pure/General/linear_set.scala
author wenzelm
Tue, 01 Sep 2009 11:52:19 +0200
changeset 32464 5b9731f83569
child 32465 87f0e1b2d3f2
permissions -rw-r--r--
added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
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
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     3
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     4
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
     5
*/
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     6
package isabelle
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
     7
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
object Linear_Set
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    10
{
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    11
  def empty[A]: Linear_Set[A] = new Linear_Set[A]
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    12
  def apply[A](elems: A*): Linear_Set[A] =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    13
    (empty[A] /: elems) ((s, elem) => s + elem)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    14
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    15
  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
    16
  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
    17
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    18
  private def make[A](first: Option[A], last: Option[A], b: Map[A, A]): Linear_Set[A] =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    19
    new Linear_Set[A] {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    20
      override val first_elem = first
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    21
      override val last_elem = last
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    22
      override val body = b
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
}
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    25
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
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
    28
{
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    29
  /* representation */
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
  val first_elem: Option[A] = None
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    32
  val last_elem: Option[A] = None
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    33
  val body: Map[A, A] = Map.empty
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
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    36
  /* basic methods */
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    37
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    38
  def next(elem: A) = body.get(elem)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    39
  def prev(elem: A) = body.find(_._2 == elem).map(_._1)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    40
  override def isEmpty: Boolean = !last_elem.isDefined
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    41
  def size: Int = if (isEmpty) 0 else body.size + 1
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    42
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    43
  def empty[B] = Linear_Set.empty[B]
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    44
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    45
  def contains(elem: A): Boolean =
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    46
    !isEmpty && (last_elem.get == elem || body.isDefinedAt(elem))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    47
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    48
  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
    49
    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
    50
    else hook match {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    51
      case Some(hook) =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    52
        if (!contains(hook)) throw new Linear_Set.Undefined(hook.toString)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    53
        else if (body.isDefinedAt(hook))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    54
          Linear_Set.make(first_elem, last_elem, body - hook + (hook -> elem) + (elem -> body(hook)))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    55
        else Linear_Set.make(first_elem, Some(elem), body + (hook -> elem))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    56
      case None =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    57
        if (isEmpty) Linear_Set.make(Some(elem), Some(elem), Map.empty)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    58
        else Linear_Set.make(Some(elem), last_elem, body + (elem -> first_elem.get))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    59
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    60
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    61
  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
    62
    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
    63
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    64
  def +(elem: A): Linear_Set[A] = _insert_after(last_elem, elem)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    65
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    66
  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
    67
    elem match {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    68
      case Some(elem) =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    69
        if (!contains(elem)) throw new Linear_Set.Undefined(elem.toString)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    70
        else if (!body.isDefinedAt(elem)) 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
    71
        else if (body(elem) == last_elem.get) Linear_Set.make(first_elem, Some(elem), body - elem)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    72
        else Linear_Set.make(first_elem, last_elem, body - elem - body(elem) + (elem -> body(body(elem))))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    73
      case None =>
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    74
        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
    75
        else if (size == 1) empty
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    76
        else Linear_Set.make(Some(body(first_elem.get)), last_elem, body - first_elem.get)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    77
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    78
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    79
  def delete_between(from: Option[A], to: 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
    80
    if(!first_elem.isDefined) this
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    81
    else {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    82
      val next = if (from == last_elem) None
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    83
                 else if (from == None) first_elem
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    84
                 else from.map(body(_))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    85
      if (next == to) this
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    86
      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
    87
    }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    88
  }
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    89
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    90
  def -(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
    91
    if (!contains(elem)) throw new Linear_Set.Undefined(elem.toString)
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    92
    else delete_after(body find (p => p._2 == elem) map (p => p._1))
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    93
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    94
  def elements = new Iterator[A] {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    95
    private var next_elem = first_elem
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    96
    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
    97
    def next = {
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    98
      val elem = next_elem.get
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
    99
      next_elem = if (body.isDefinedAt(elem)) Some(body(elem)) else None
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   100
      elem
5b9731f83569 added linear_set.scala from http://isabelle.in.tum.de/repos/isabelle-jedit/rev/d567692f9717
wenzelm
parents:
diff changeset
   101
    }
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
}